Дневник на промените
Дневникът на промените се води само на английски.
All notable changes to this project. The format follows Keep a Changelog, and the project uses Semantic Versioning: agents and connectors of a major version work with every server of that major version.
Unreleased
Added
-
Hand-drawn charts, illustrations and date pickers: charts in Axis and Edge are drawn in the Ink & Strata hand (ink-outlined bars and slices, wobbly lines, pencil gridlines; the palette starts with violet). Empty lists, no results, errors and 404 pages show small hand-drawn illustrations. Every date and date-and-time field opens a hand-drawn calendar instead of the browser's. @entrosity/ui 0.7.0:
SketchIllustration,EmptyState,DatePicker([Conventions]). -
Faster pages: the hand-drawn look no longer runs an SVG filter on every outline, chart and list row, and sticky headers no longer blur what scrolls under them, so busy pages (Axis devices and screen wall, Matrix rooms, Sphere live view) scroll and update smoothly again (@entrosity/ui 0.7.2).
-
Responsive on phones and tablets: Hub, Axis, Edge, Matrix, Sphere and the website work from 320px wide: no sideways scrolling, tables scroll in their own box, filters and forms stack, grids reflow and dialogs fit the screen (@entrosity/ui 0.7.1).
-
Entrosity Sphere, optimise for live view checks the streams: after tuning, the connector watches each camera's sub stream until two keyframes arrive and measures the interval (
measured_mson everyChannelTune; the job now has 5 minutes). Cameras apply a value the NVR passes on only after some minutes, and some keep their own (it syncs back to the NVR), so a camera whose stream keeps the old interval is listed as not applied yet (optimise again later) or, when the NVR already held the shorter interval, as keeping its own (set it on the camera); the dialog also says how many cameras were checked. Needs the updated connector ([NVRs]). -
Entrosity Sphere, optimise for live view: tenant admins can choose Optimise for live view on a connected NVR's page: every camera's sub stream (the one grids show) is set to send a keyframe at least every 1, 2, 3 or 4 seconds (1 recommended; frame rate × seconds frames), so a viewer opening a camera waits less for the first picture (Dahua cameras default to one every 2 seconds). Intervals already as short are kept, main streams, which the NVR records, are never changed, and sub streams use a little more bandwidth. The NVR's settings are read back, since an NVR may accept a value an IP camera does not take; the dialog sums up N changed, N already fine, N not changed and lists the failures by camera. Audited as
nvr.tune_live. API:POST /tenants/{tenantID}/nvrs/{nvrID}/tune-live{keyframe_seconds}(1–4, default 1; permissionnvrs:manage), a job whose result is anNvrLiveTuneResult;409 nvr_offlinewhen the NVR is disconnected,409 connector_offline. Connector jobsphere.nvr.tune_live(LiveTuneJob,LiveTuneResult; laneprobe, 3 minutes), DahuaEncode[i].ExtraFormat[0].Video.GOPthroughconfigManagersetConfig; the simulator implements it. Needs the updated connector ([NVRs], [Sphere connector protocol]). -
Entrosity Vertex (beta): Active Directory management: a new product at
/vertexon the Hub's host, with sign-in on Entrosity Hub (productvertex, roles Tenant admin and Helpdesk; Hub platform admins are global admins). Users with every attribute (binary values asb64:, a deny list for identity, security and password attributes), password resets, unlock, enable/disable, move, rename, delete, group membership and actions on up to 500 users; groups and members; OUs; Group Policy (create, rename, status, delete, links with enforce and order, registry-based settings, security filtering, backups on the domain controller before every change, the XML report; the default domain policies are read-only); fine-grained password policies; and CSV bulk imports of up to 10,000 users (;or,,create/update/upsert,attr:<ldapName>columns, groups by DN or name, a preview of every row, commit with step-up, a result file without passwords). Vertex has no connector of its own: every request is an operation run as a job on the tenant's Axis connector on a domain controller, as the AD account configured in Vertex (Windows PowerShell 5.1, ActiveDirectory and GroupPolicy modules, a loopback PowerShell session; the account needs Remote Management Users). Safety layers: write switches per kind and for deletes (all off by default), managed OUs, protected objects (adminCount=1, critical system objects, built-in RIDs), change limits (600 per user, 2,000 per tenant per minute), step-up for settings, deletes and import commits, the author's rights checked again when the connector fetches the job's secrets (author_revoked), the connector's local guard (rmm-connector vertex guard accept), and the audit log. The AD password and new passwords are stored encrypted (VERTEX_CREDENTIALS_KEY), handed to the connector once and never returned. The API is ready; the web interface is in development, and Vertex is not deployed yet: the Hub's migration0013_vertex_productregisters it disabled and in beta ([Entrosity Vertex], [Setting up the domain controller], [Bulk import], [Running Entrosity Vertex], [Vertex API], [Vertex protocol]). -
Axis for Entrosity Vertex: an internal listener for Vertex (
RMM_INTERNAL_ADDR,:8089, on only withRMM_VERTEX_INTERNAL_URLandRMM_VERTEX_AXIS_TOKEN): Vertex lists a tenant's connectors and queues, reads and cancelsvertex.op/vertex.readjobs there. The connector API gainsPOST /api/connector/v1/vertex/jobs/{jobID}/secretsand…/chunks, relayed to Vertex only for live Vertex jobs of the asking connector; Axis stores no Vertex secrets and tells Vertex when a Vertex job finishes ([Configuration]). -
Site connector, Vertex capability: Windows builds announce
vertexand run Vertex jobs in two new lanes (vertex, one change at a time;vertex-read, two reads). Changes need the new local guardvertex-guard.json, changed only from an elevated prompt withrmm-connector vertex guard show|accept|set|reset: accept the managed OUs, switch on GPO (--gpo), password policy (--pso) and delete (--deletes) changes, and set the cap of writes per minute (--max-writes-per-minute, default 120; raise it to at least 200 for bulk imports). GPO backups go to%ProgramData%\Entrosity\Vertex GPO Backups([Site connector], [The connector's local guard]). -
Hub, reset a user's authentication: platform admins can choose Reset authentication on a user's page to turn off the user's two-factor authentication (lost phone and recovery codes), reset their password (the old one stops working at once and a link to choose a new one, valid for 24 hours, is e-mailed), or both. The user is signed out everywhere and the action is audited as
user.reset_auth; you cannot reset your own. API:POST /admin/users/{userID}/reset-auth, codesself_reset,user_not_active,nothing_to_reset([Reset authentication]). -
Axis screen wall, 30 screens, 720p and lock: the wall shows up to 30 computers of a room; an enlarged tile streams 720p (1280×720, about 5 pictures a second) and goes back to the small picture when you return to the grid. Each live tile has a lock button that locks the computer's own keyboard and mouse, and Lock all / Unlock all lock the whole room; the lock ends with the session at the latest (Ctrl+Alt+Del lifts it until that screen is gone). Remote desktop gets Lock keyboard and mouse in control mode: the user cannot interfere, the technician's input still works. Stream messages
lock/locked(control sessions and wall tiles) andlarge(wall tiles), relayed by the server; older agents ignore them. Needs the new agent (WindowsBlockInputon the helper's input thread) ([Screen wall], [Remote desktop]). -
Axis deployments, several packages at once: the deployment wizard picks one or more packages (at most 20); several become one deployment per package with the same targets and options, in the order chosen, created in one transaction. A computer installs them one after another; a job waiting in the agent behind another no longer times out (a job acknowledged but not started is timed from when the jobs before it finished; agents now report when a job starts), and a restart a reboot policy asks for waits until the last queued package. API:
POST /tenants/{tenantID}/deployments/batch(package_ids), permissiondeployments:create([Deployments]). -
Axis screen wall: Screen wall watches up to 26 screens of a computer room at once, view only: pick an Entrosity Matrix room and every computer's live picture (about once a second, at most 640×400) shows in a grid; click one to enlarge it. Rooms and their computers come from Matrix (the room's FortiGate address group, matched to Axis devices by name). Technicians and administrators see every room; technicians always show the session bar on the computers, administrators choose. The users are never asked. A tile that cannot show a picture says why (not in Axis, offline, in a remote session, agent update needed); a wall never interrupts a remote desktop session. New Axis role Teacher (Hub product role
teacher): only the screen wall, for the rooms granted to them on Matrix's Room rights page, without the session bar; a right withdrawn in Matrix ends their screens within about 15 seconds. Needs agents that announceremote_wall(they update themselves) andMATRIX_AXIS_TOKEN(compose:RMM_MATRIX_INTERNAL_URL,RMM_MATRIX_AXIS_TOKEN, Matrix'sMATRIX_INTERNAL_ADDR:8086). API:GET /tenants/{tenantID}/screen-wall/rooms,POST /tenants/{tenantID}/screen-wall/open, permissionscreens:view, codesremote_busy,remote_wall_unsupported,screen_wall_unavailable;remote_desktopjob fieldprofile; Axis migration0017_screen_wall, Hub0012_axis_teacher([Screen wall], [Roles]). -
Changing your e-mail: the Hub's Account page has an E-mail card: enter the new address and your current password; the change applies when the link sent to the new address is opened (24 hours, newest link only), the old address is told, and you are signed out everywhere. API:
POST /me/email,POST /auth/email/confirm; migration0010_email_changes([Your account]). -
Entrosity Matrix, allowed sites: the new Allowed sites page lists the domains a room's computers can still reach while its internet is off: a list for all rooms of a firewall and, optionally, each room's own list. Domains only (
example.comor*.example.com, at most 200 per list; a pasted link is saved as its host, international names in punycode), no paths and no SSL inspection. Tenant admins edit every list, operators the lists of the rooms granted to them, viewers only look. Save sends the whole list to the connector, which checks the list's version, asks Matrix to authorize each write, creates FQDN address objectsmatrix-site:<domain>, sets the members of the list's FortiGate address group (Matrix allowed sites,Matrix allowed sites <room>) and confirms by reading it back; an unconfirmed save is never repeated automatically (Check / retry). Entries Matrix did not create stay read-only. Matrix never creates policies: each list's group and ACCEPT policy are set up once from the CLI that FortiGate setup shows (tenant admins). Needs the firewall's new Allow editing allowed sites (off by default),matrix-connector guard set <id> --site-writes onon the connector computer and an updated connector (older ones keep working without allowed sites:connector_outdated). Room cards show N allowed sites; changes are in the history as Allowed sites. API:GET/PUT /tenants/{tenantID}/firewalls/{firewallID}/allowed-sites[/{list}],GET …/allowed-sites/setup-cli, permissionallowed_sites:manage, eventmatrix.sites, jobmatrix.sites.set, codesconnector_outdated,sites_not_set_up,invalid_domain; migration0003_allowed_sites([Allowed sites], [Setting up the FortiGate], [Matrix API]). -
Axis deployment targets: Choose computers in the targets step of a deployment (and of Run script) opens a picker: search computers by name, user, IP address or serial number, tick them or Select all shown, or tick one or more Active Directory OUs to add all their computers and then untick single computers, and remove chosen ones; before, specific devices could only be chosen from the device list ([Deployments]).
-
Back button: every app (Hub, Axis, Edge, Sphere) has a Back button in the header that returns to the previous screen; it is hidden on the first screen opened in the app.
-
Coloured statuses everywhere: statuses in every app use one colour scheme from
@entrosity/ui(green online, connected, active or done; blue in progress; amber pending or unknown; red offline, refused or failed; grey idle). In Sphere, an NVR's Status and Wanted are green when online or connected; an offline Axis device's dot is red ([Conventions]). -
Entrosity Sphere administration: the global admin Overview now matches Axis: NVRs online and failing, cameras, connectors online, unacknowledged alarms of the last 24 hours, live streams and users, and a table of the same counters per tenant. The new Connector releases page lists every stored connector installer with a Download button (a fresh one-hour link per click), marks the release connectors are updated to, counts the connectors by version and shows the release public key ([Connectors → Connector releases]).
-
Axis release downloads: Download on Agent releases saves a release's MSI as
rmm-<component>-<version>.msi(global admins; drafts once uploaded; audited asrelease.download) ([Agent releases]). -
Entrosity Edge, disabling controllers: Disable controller on a controller's page (tenant admins, after a confirmation) makes Edge and its connector leave the controller alone, for example while the vendor's old software manages it or while it is serviced: its open configuration jobs are cancelled, the connector stops polling, configuring and setting its clock (
edge.controller.remove), card and access changes are not sent to it, its events are not collected, and whatever the connector still reports about it is ignored. It shows Disabled in the list and in the page header, is not counted on the dashboard, and Open door, Test connection and Send configuration again are hidden (the API refuses them withcontroller_disabled, 409); its settings can still be edited. Enable controller sends its complete configuration again. Audited ascontroller.update. API:enabledon controllers and inPATCH /tenants/{tenantID}/controllers/{controllerID}, sync statusdisabled; migration0005_controller_enabled([Disable a controller]). -
Entrosity Edge, editing controllers: Edit controller on a controller's page (tenant admins) changes its name, site, connection (TCP/IP or RS-485), address, bus address and doors layout; only what changed is sent, and the PIN keeps its own dialog. Changing Doors rebuilds the doors and readers as adding the controller with that mode does: door 1 stays with its id, name and access groups, door 2 is added (with the Wiegand 2 reader as its entry reader) or removed (the reader becomes door 1's exit reader), and the new layout is sent to the controller right away. Door 2 cannot be removed while access groups use it:
door_in_use(409) names the groups. Readers can now be named on the controller's page. API:door_modeinPATCH /tenants/{tenantID}/controllers/{controllerID}([Edit a controller], [Change the doors layout]). -
Entrosity Edge, card numbers as printed: Wiegand 26 cards are entered and shown by the 10-digit number printed on them, e.g.
0015592682(facility code 237, card number 60650): Register card takes Card number by default, with Facility code + number as the alternative, and cards, the cardholder's page, the live monitor, the history and the dashboard show the printed number with facility code:card number beside it. Card search matches the printed number with or without its leading zeros. The API is unchanged (facility_codeandcard_number) ([Wiegand 26 card numbers]). -
Entrosity Edge connector development builds and self-update: every change to the connector publishes its MSI and EXE as the rolling pre-release
devofentrosity-edge-connector(versions0.0.<build>-dev.<commit>, each upgrading the previous; the first tagged release upgrades them). CI also publishes every build to Edge (tagged releases to thestablechannel, pre-releases and dev builds tobeta), which signs it and offers it to the connectors: connectors update themselves, verify the release signature, install the new MSI from a scheduled task and roll back to the previous version if it does not start. Each connector follows the Stable channel by default; tenant admins switch it to Beta (development builds) in the new Updates column of Connectors, which also shows Updating to X while an update is on its way. The MSI now also installs over a newer version (for the rollback). NeedsEDGE_MASTER_KEY,EDGE_RELEASE_SIGNING_KEY(edge-server release-keygen) andEDGE_RELEASE_TOKENon the server, andRELEASE_PUBLIC_KEY,EDGE_RELEASE_TOKENandEDGE_RELEASE_APIin the connector's repository. Connectors installed before self-update must be upgraded by hand once ([Connectors → Updates], [Running Entrosity Edge]). -
Products in beta: a platform admin can put a product in beta (Administration → Overview → Products): only platform admins see and open it, grayed out with a Beta badge in the launcher; organizations and their users neither see it nor get its sign-in tokens until it is released. Entrosity Edge starts in beta ([Products in beta]).
-
Entrosity Edge: a new product for cloud-managed physical access control with TRAcK ACCESS TrackBase002 controllers, at
/edgeon the Hub's host, with sign-in on Entrosity Hub (productedge, roles Tenant admin, Operator and Viewer). Cardholders with validity periods, Wiegand 26-bit cards and iButton keys, weekly schedules with holidays, and access groups; each controller receives its complete configuration (up to 2,000 cards) and shows whether it is in sync; a live monitor and searchable history of every door event; remote door opening. An on-site Windows connector (edge-connector.msi) links the controllers to Edge, keeps working through outages and delivers every event exactly once. The connector'strackbase002driver speaks the Track Access controller protocol over TCP (see below); a built-in simulator runs complete trials without hardware. English and Bulgarian ([Entrosity Edge], [Edge API reference]). -
Entrosity Edge, TrackBase002 driver: the connector configures TrackBase002 controllers over TCP (cards, up to 16 time zones, applied as differences; Send configuration again rewrites everything), reads their event log, keeps their clock within 2 seconds and opens doors remotely. Each controller's PIN is set in Edge (Controller PIN when adding it, or Set PIN/Change PIN/Clear PIN on its page), stored encrypted with
EDGE_MASTER_KEY, never shown again, and sent to the connector only with its jobs; the connector no longer readstrackbase.json(a file left on disk is ignored, and uninstall still removes it). Controller discovery has no PINs: found controllers are listed without their firmware until they are added with a PIN. Limits: TCP only, no holidays on the controller, one set of schedules per card, 24-bit card numbers, door states not reported yet. The protocol has not been verified against a live controller yet: verify on one controller before moving a site over ([Controllers], [Edge connector]). -
Entrosity Sphere: a new product for video management of Dahua NVRs (and OEM NVRs on the same firmware) in the browser, at
/sphereon the Hub's host, with sign-in on Entrosity Hub (productsphere, roles Tenant admin, Operator and Viewer). Live camera grids of 1, 4, 9 or 16 tiles and a single camera view over WebRTC with snapshots and full screen, PTZ with presets, recording search and playback on a timeline, the NVRs' alarms live with acknowledgement, saved views (personal or shared), and connecting to and disconnecting from NVRs. An on-site Windows connector (sphere-connector.msi) reaches NVRs that are not on the Internet: it connects out to Sphere (TCP 443 to the Hub's host), publishes a camera's stream to Sphere's media server (TCP 8322 tomedia.entrosity.com, a DNS-only host name, since the Hub's host is behind Cloudflare) only while someone watches it (once, whatever the number of viewers), and delivers every alarm exactly once. NVR passwords are stored encrypted and never shown again. Sphere starts in beta (platform admins only) and needs the DNS-only media host (SPHERE_MEDIA_DOMAIN) and ports 8322/tcp and 8189/udp+tcp on the server; a built-in simulator runs trials without an NVR. English and Bulgarian ([Entrosity Sphere], [Live view], [Playback], [Alarms], [NVRs], [Running Entrosity Sphere], [Sphere API reference]). -
Entrosity Sphere, grid splits and PTZ in the grid: Layout in live view opens a picker with a drawing of each SmartPSS split: 1, 2×2, one big + 5, one big + 7, 3×3, 4×4, 5×5, 6×6 and 8×8 (up to 64 tiles). Saved views store any of them (API
layout1, 4, 6, 8, 9, 16, 25, 36 or 64, up to 64 cells; migration0003_view_splits). Tiles of 5×5 and larger splits drop the NVR name and keep only Show only this camera and Close; empty ones show a +. Operators and tenant admins get a collapsible PTZ panel under the camera list that moves the camera of the selected (or expanded) tile, with Show PTZ controls for cameras the NVR does not report as PTZ ([Live view], [PTZ cameras]). -
Entrosity Sphere, playback of several cameras: tick up to 64 cameras in the searchable camera tree; they play side by side, in sync, from the moment clicked on a shared timeline (a row per camera, six visible, the rest scroll; 24 h or 1 h zoom). A camera that did not record at that moment says so; when none did, playback starts at the next recording of any of them. Playback uses the same splits, growing to hold the selection ([Playback]).
-
Entrosity Sphere connector download and self-update: Download connector on Connectors (tenant admins) downloads the newest connector installer through a link valid one hour, and new enrollment tokens link it too. CI uploads every connector build to Sphere (tags to
stable,-suffixtags and every push tomaintodev), which signs it and keeps the newest ten (migration0004_connector_releases); connectors built with the release key update themselves to the newest release ofSPHERE_CONNECTOR_UPDATE_CHANNEL, verify its signature, install it from the scheduled taskSphereConnectorUpdateand roll back if the new version does not start (the MSI now installs over a newer version). Version shows updating to X, or update to X in amber for connectors that must be reinstalled by hand once. NeedsSPHERE_RELEASE_SIGNING_KEYandSPHERE_RELEASE_TOKENon the server andRELEASE_PUBLIC_KEY,SPHERE_RELEASE_TOKENandRELEASE_PUBLISH_ENABLEDinentrosity-sphere-connector([Connectors → Updates], [Running Entrosity Sphere]). -
Entrosity Matrix: a new product for switching the internet access of computer rooms on and off through FortiGate firewall policies, at
/matrixon the Hub's host, with sign-in on Entrosity Hub (productmatrix, roles Tenant admin, Operator and Viewer). A room is a FortiGate IPv4 policy whose name matches a per-firewall pattern (RE2 with a(?P<room>…)group) and whose direction is exactly the configured source → destination; Matrix only ever changes such a policy's status and the /32 address objects of its address groups. Rooms as cards by building with a confirmed enable/disable, disable until… (in 45 minutes, at the end of the school day or at a chosen time; switched back on automatically, with Schedules listing upcoming and failed re-enables), bulk changes by selection or building, addresses and groups (change a computer's IP, add a computer, Check / retry of interrupted operations), per-operator room rights, and a history of every change and refusal with its steps. An on-site Windows connector (matrix-connector.msi) reaches the FortiGate's REST API on the LAN: before every write it re-reads the policy, needs a local guard accepted on its computer (matrix-connector guard accept), asks Matrix to authorize the write and confirms it by reading it back; an unconfirmed write is never repeated automatically. FortiGate API tokens are stored encrypted (MATRIX_CREDENTIALS_KEY) and never shown again; both write switches are off by default; a read-only check (also offline,matrix-connector check) warns when a later ACCEPT policy would still let a disabled room out, since a disabled rule alone does not prove that the internet is off.matrix-server import-stop-internetbrings over the room rights and history of the single-school panel it replaces. Matrix starts in beta (platform admins only), is optional per host (MATRIX_ENABLED, compose profilematrix), and has a built-in simulator for trials. English and Bulgarian ([Entrosity Matrix], [Setting up the FortiGate], [Moving from the old panel], [Running Entrosity Matrix], [Matrix API reference]). -
Bulgarian interface: Entrosity Hub and Axis are translated into Bulgarian. English stays the default; the language button in the header (and on the Hub's sign-in pages) switches between English and Български, and the choice is shared by the Hub and Axis in the browser. Dates, numbers and known server errors follow the language ([Your account]).
-
Documentation: the documentation is available in Bulgarian at
/docs/bg/. English stays the default; the language menu in the navbar switches between the two ([Writing docs]).
Changed
- Axis agent icon:
rmm-agent.exe, its windows (taskbar and Alt+Tab) and the installer's entry in Settings › Apps show a hand-drawn Entrosity icon instead of Windows' default one. Needs agent 0.1.18-dev or later. - Axis agent, session bar, consent prompt and restart notice: the bar a user sees during a remote session, the prompt asking whether a technician may connect, and the scheduled restart or shutdown notice are drawn in the Ink & Strata look (paper panel with a hand-drawn ink outline, violet strata, hatch marks, ink-outlined buttons); behaviour and texts are unchanged. Needs agent 0.1.17-dev or later (0.1.15-dev for the bar and the prompt).
- Axis screen wall, session bar off by default: for administrators, Show the session bar on the computers now starts unticked; tick it to show the bar. Technicians still always show it, teachers never do ([Screen wall]).
- Entrosity Sphere, faster camera switching: measured in production on 2026-10-09, switching to a camera took 4.1–5.3 seconds when its stream was not running (the connector opening it on the NVR, then the wait for the camera's next keyframe, then WebRTC) and 1.6–2.8 seconds when it was. A live stream nobody watches now keeps running for 5 minutes (sub streams) or 2 minutes (main streams) instead of 30 seconds, so switching back skips the start on the NVR (
SPHERE_LIVE_IDLE_GRACE,SPHERE_LIVE_IDLE_GRACE_MAIN, Go durations, at least10s); idle streams use the site's upload while they run. At a stream limit, the idle stream unwatched the longest stops to make room instead of the viewer gettingstream_limit; streams with viewers are never stopped, and playbacks still stop when their viewer leaves. A stream is live as soon as the connector's start job succeeds, the browser prepares the WebRTC connection while the camera starts, and the connector connects to the media server while the NVR answers instead of after it. A wanted stream a connector's report leaves out for 45 seconds is started again even if it was live (a connector restart) ([Live view], [Running Entrosity Sphere]). - Entrosity Matrix, teachers see only their rooms: teachers no longer see the rooms not granted to them (they were shown View only): the rooms, address groups, allowed-sites lists (the list for all rooms stays visible, read only), re-enable schedules, history and live updates hold only their rooms, and firewalls without any of their rooms are left out; the server never sends the others. A teacher without rooms sees No rooms are assigned to you yet. A teacher's change of a room not granted to them now answers 404
unknown_room(was 403room_not_granted), like a room that does not exist, and is still recorded as refused. Viewers, tenant admins and global admins are unchanged ([Roles and permissions], [Room rights]). - New look, "Ink & Strata": the website, Entrosity Hub, Axis, Edge, Matrix, Sphere and this documentation take on the hand-drawn look of the brand artwork: grey paper, wobbly ink outlines with irregular corners and hard ink shadows, violet wave strata sweeping in from the corners,
#and////doodles and an underlined wordmark; the sign-in pages are framed like the artwork, and the dark theme becomes an ink-on-violet night. The font is Geist. Nothing moves or changes behaviour. Shipped in@entrosity/ui0.6.0 (tokens--ink,--shadow-ink,--wave-1…--wave-6,--glare; classessketch,sketch-field,sketch-edge-*,sketch-underline,hatch-*,paper; componentsSketchWaves,HatchMark,SketchFrame,SketchDefs) ([Conventions]). - Axis, teachers get no e-mail: alert e-mails (immediate, roll-ups, digests, quiet-hours summaries and resolutions) are never sent to members with the Teacher role, whatever their saved preferences; teachers no longer reach My notifications ([Alerts]).
- Entrosity Matrix: the role Operator is now called Teacher (Hub product role
teacher), with the same rights: it switches the rooms granted to it on Room rights. Existing operators become teachers (Hub migration0011_matrix_teacher, Matrix0005_teacher_role); Matrix still accepts the old id while it catches up. Error codenot_operatoris nownot_teacher([Roles and permissions]). - Repositories: the
entrosity/RMMmonorepo is split into separate repositories with their history:entrosity-shared-go,entrosity-ui,entrosity-axis.backend,entrosity-axis.frontend,entrosity-axis-agent,entrosity-axis-connector,entrosity-hub.backend,entrosity-hub.frontend,entrosity-infraandentrosity-docs([Repositories]).@entrosity/uiis published to GitHub Packages and the apps are bumped automatically on each release. - Production: since 2026-09-26 production is deployed from the split repositories: every new
mainimage of a backend, a frontend or the documentation triggers thedeployworkflow ofentrosity-infra, which ships the imagesaxis-backend,hub-backendandentrosity-web(formerlyrmm-backend,platform-backendandrmm-web) to the host, now in/opt/entrosity/deploy([Continuous deployment]). The monorepo's deploy and release workflows are disabled; agent and connector builds are published to production byentrosity-axis-agentandentrosity-axis-connector(a dev build on every push tomain), and dev builds are now versioned0.1.<run>-dev.<sha>so they sort above the monorepo's0.0.xdev builds. - Production host: production moved to a new server (93.123.16.96) on 2026-09-27, which it shares with the website, the helpdesk and Vaultwarden: nginx keeps ports 80/443 and routes the Entrosity host names to Caddy by SNI; the new
WEB_HTTP_PORTandWEB_HTTPS_PORTpublish Caddy on loopback ([TLS → Behind an existing nginx]). DNS-only records (files.manage,media) now point at the new address. - Database: production runs PostgreSQL 18 (was 16), moved with a full dump and restore; the PostgreSQL 16 data is kept for rollback.
- Axis device list: long site names in the Site column are shortened with an ellipsis so the table stays narrow; hover over one to see the full name ([Devices]).
- Entrosity Sphere limits: each NVR serves 4 playbacks at once by default (was 2,
SPHERE_MAX_PLAYBACKS_PER_NVR), and a connector publishes up to 64 streams, enough for an 8×8 grid (was 32:SPHERE_MAX_STREAMS_PER_CONNECTORon the server,SPHERE_CONNECTOR_MAX_STREAMSon the connector). A playback stops as soon as its viewer leaves instead of after 30 seconds, and closing or reloading the tab ends the viewer's streams at once ([Limits]).
Removed
- Entrosity Matrix, Entrosity services: Matrix no longer keeps a built-in
Matrix Entrosity servicesgroup: while a room's internet is off, only the sites teachers and admins list are reachable. The Entrosity Axis agents of such a room lose their connection until its internet is on again, unless an admin adds the needed domains to a list (advised against for the Hub and Axis management, which are behind Cloudflare: allowing them opens Cloudflare's shared addresses). The Allowed sites page no longer shows the locked Entrosity services list, the firewall settings no longer have Keep Entrosity services reachable, the setup CLI no longer adds the group to the shared policy, andMATRIX_SERVICE_DOMAINSis no longer read. The connector refusesmatrix.services.syncas an unsupported job, no longer reports the group and dropsguard set --service-writes(guard files withallow_service_writeskeep working); the server refuses a leftover sync (services_removed). Old Entrosity services entries stay in the history, shown as Entrosity services (removed). Migration0004_remove_entrosity_servicesdropsservices_enabled, deletes open sync jobs and cancels their pending changes. On FortiGates set up earlier an admin can remove the empty group ([Allowed sites], [Removing the old Entrosity services group], [Running Entrosity Matrix]).
Fixed
- Axis dropdowns: every dropdown now looks like the text fields (same border, background and focus ring); the device filter's Site, Source and Active Directory OU were black boxes whose focus ring spilled out of the panel. Shared as
@entrosity/ui/native-select. - Entrosity Hub launcher: the product cards in a row line up again: the role, organization and Open rows sit at the bottom of every card instead of moving down with a longer description or the beta note.
- Entrosity Edge connector, TrackBase002 clocks: a controller whose clock came back invalid was left with a meaningless clock: the connector read the clock back after setting it with a reply that carries no clock (0x27, all zeros on live controllers), so it took every layout for rejected, wrote the last one tried (BCD) and gave up. It now reads the clock back with a status read, leaves the protocol's layout on the controller when none reads back valid, and tries again every 10 minutes instead of giving up ([Edge connector]).
- Entrosity Hub: the browser tab showed an old icon (the portal's early lightning-bolt logo, kept in browsers' favicon cache) instead of the Entrosity mark that Axis shows. The Hub's icon is now served under a new address, so every browser picks up the Entrosity mark.
- Entrosity Hub: in Administration → Users, a user's Access card showed the product role dropdowns without saying which product each one was for. Each role now has its product's name next to it ([Platform administration]).
[1.0.0] – unreleased
This is the first production release. It adds production hardening on top of the feature set of phases 0–5.
Features (phases 0–5)
- Identity: multi-tenant portal with global admins, tenant admins, technicians and viewers. Sign-in with argon2id passwords, TOTP and recovery codes, rotating refresh cookies, invitations, password reset, and an audit log.
- Devices: Windows agent (Go service) with enrollment tokens, WebSocket connection with an HTTPS polling fallback, and full inventory (hardware, software, updates, services, users, network). Live device list, filters, metrics and device actions: inventory, reboot, shutdown, uninstall from inventory, wake-on-LAN, merge.
- Active Directory: a site connector per site does LDAP(S) sync of AD computers, pushes the agent over WinRM or SMB, and sends wake-on-LAN packets.
- Packages and deployments: MSI, EXE, winget and PowerShell packages with detection rules and browser uploads to object storage. Deployments go to devices, filters or all devices, with schedules, maintenance windows, concurrency, retries, reboot policies and live progress.
- Scripts: a versioned script library (PowerShell, PowerShell 7, cmd) with typed parameters and live output. Run-as-logged-on-user.
- Alerts: rules for offline devices, disk, CPU/memory, outdated agents, failed deployments, AD sync and connectors. Global rules with tenant overrides, e-mail notifications and digests.
- Self-update: signed (Ed25519) agent and connector releases with channels, rollout percentages and watchdog rollback.
Added in phase 6 (hardening)
- Row-level security (migration 0007):
- The server runs as
rmm_app, and every tenant request is scoped in PostgreSQL. - Composite tenant foreign keys, and an append-only audit log.
- The server runs as
- An authorization fuzz test with 82 cross-tenant cases.
- Retention:
- A daily cleanup with defaults per category, configurable via
RMM_RETENTION_*. - Per-tenant job and audit windows under Tenant settings.
- Management of the metrics partitions.
- A daily cleanup with defaults per category, configurable via
- Performance:
- Migration 0008 adds indexes and a trigram device search.
- Software filters use a SECURITY DEFINER function.
- List and dashboard queries run in parallel.
- A seed tool (
cmd/seed) and an API benchmark (cmd/apibench), with baselines indocs/perf/.
- Load handling, tested with 5,000 simulated agents and a 1,000-device
deployment:
- batched heartbeats;
- inventory section fingerprints;
- ingestion back-pressure;
- enrollment token reads without row locks;
- deadlock-safe deployment result handling.
- Multiple replicas:
- Sign-in limits are stored in PostgreSQL (migration 0009), so they hold across replicas.
- Revocation and tenant suspension take effect on every replica.
- Production deployment:
deploy/docker-compose.prod.ymlwith Caddy (automatic TLS, security headers, CSP, WebSocket/SSE-aware proxy, SPA).- A distroless non-root backend image, and a portal image running Caddy as uid 10001.
- A tuned PostgreSQL with a WAL archiving hook, MinIO, a systemd unit,
and
.env.prod.example. - A
healthchecksubcommand. The backend refuses to start on a mismatched schema, andmigrate forcefixes a dirty migration.
- Monitoring:
- Prometheus metrics on an internal listener (
RMM_METRICS_ADDR, plus pprof). - A Grafana dashboard, 7 alert rules, and
deploy/docker-compose.monitoring.yml.
- Prometheus metrics on an internal listener (
- Operations:
deploy/scripts/backup.sh,restore.shandupgrade.sh(rolling restart), with a restore drill.rmm-server rotate-master-key, andRMM_JWT_SECRET_OLDfor JWT secret rotation.RMM_MIN_AGENT_VERSIONforces updates regardless of rollout.
- Security:
POST /auth/sse-tokenissues short-lived, tenant-bound event stream tokens.- Log redaction, and a WebSocket origin check test.
- A
security.ymlworkflow (govulncheck, gosec, pnpm audit, gitleaks, Trivy, SBOM) and Dependabot. SECURITY.mdanddocs/security-review.md.- Release images are scanned, pushed to ghcr.io and published with SPDX SBOMs.
- Documentation:
- A documentation site (Docusaurus,
website/), served at/docs/by the portal's Caddy: user guide, administration, operations, reference, development, and the API reference rendered frombackend/api/openapi.yaml. docs/operations.mdanddocs/user-guide.md.- Rendered API reference in
docs/api/index.html(make api-docs). - Refreshed architecture, data model, protocol and development guides.
- A documentation site (Docusaurus,
Added after phase 6
- Configurable Hub sign-in limits.
PLATFORM_AUTH_RATE_PER_MINUTE(default 10 per client IP) andPLATFORM_EMAIL_RATE_PER_MINUTE(default 5 per e-mail address) set how many sign-in and other public auth attempts the Hub accepts per minute. - Grouped offline e-mails and more notification controls. Devices going offline are no longer mailed one by one: one e-mail per batch (5, 15, 30 or 60 minutes) lists the devices that went offline and every device currently offline, and digests include the same sections. New settings under My notifications: digest frequency (15 minutes, hourly, daily at an hour), per-type e-mail switches, e-mails when alerts resolve, and quiet hours with an option to still send critical alerts (held e-mails arrive as one summary afterwards). Migration 0014.
- Dark theme. Axis and Entrosity Hub follow the light or dark setting of the device they are opened on; a theme button (System, Light, Dark) in the header overrides it for this browser.
- Device sign-ins. The agent reports every Windows sign-in (console and Remote Desktop, with the client) and sign-out; the device's Sign-ins tab lists them. Entries are deleted 7 days after the sign-out. Migration 0015.
- CPU temperature. Heartbeats carry the hottest thermal zone (where the hardware reports one), the Metrics tab charts it, and a new alert type CPU temperature comes with a global rule (above 90 °C for 10 minutes). Migration 0016.
- Remote desktop. A Remote desktop button on an online Windows
device opens its screen in a new browser tab, to watch (View only)
or to use its mouse and keyboard (Control), optionally after the
signed-in user accepts a prompt. Built in, with nothing to install on
the technician's side: the agent captures the screen with a helper in the
console session (sign-in screen, lock screen and UAC prompts included)
and sends changed tiles as JPEG, and the backend relays the stream over
HTTPS, across replicas too. Multiple monitors, picture quality,
Ctrl+Alt+Del and Type text; one session per device, at most 8 hours.
While a session runs, the user sees a small bar naming the technician
with an End session button. Sessions end when access changes
(device decommissioned, agent revoked, tenant suspended, technician
disabled or demoted), and a viewer link opened outside the portal's
dialog asks before connecting. Only tenant and global admins
(
devices:remote_unattended) can start a session without the consent prompt or without the session bar (migration 0011); for technicians both are always on. - Branded restart and shutdown notices. Reboots and shutdowns (device
actions and package reboot policies) show every signed-in user a notice
in the Entrosity Axis design with the logo, the administrator's message,
a countdown and Dismiss, instead of the plain
msg.exebox (which was missing on Home editions). The consent prompt, session bar and notices share one UI kit in the agent. New permissiondevices:remote(technicians and admins), audit entriesremote.session_request,remote.session_startandremote.session_end, migration 0010 (remote_sessions) and theRMM_NODE_URLsetting. This replaces the RustDesk integration of the development builds; theRMM_RUSTDESK_*settings are gone. - Devices by OU: the device list has an Active Directory OU tree beside it (domain, OUs and containers with computer counts). Selecting an OU lists the devices in it and below it; Not in Active Directory lists agent-only devices. The Filters OU picker shows the same tree. The tree can be hidden and shown again (remembered per browser).
- Delete enrollment tokens: global admins can delete any enrollment
token permanently (
POST /tenants/{id}/enrollment-tokens/{tokenId}/delete), confirming with their own password (422 on a wrong one, rate-limited like sign-in). Tenant admins can still only revoke. The deletion is audited; enrolled agents and connectors are not affected. A deleted AD push token is replaced before the next push is sent. - AD computers: the page is in everyone's sidebar and shows agent
coverage for the selected OU: how many computers run the agent, how
many are being pushed, failed or never pushed, and why pushes failed
(error codes with counts, causes and fixes). Every figure is a filter.
It has the same OU tree as Devices. The list shows the agent and
push columns first, with the reason for a failure.
New:
GET /tenants/{id}/ad-computers/summary, and thepushandpush_error_codefilters onGET /ad-computers. - The
oufilter ofGET /ad-computersnow includes sub-OUs and ignores case, like the device list's. - Sidebar: global admins always see a tenant's menu (the tenant they are in, else the one they opened last), and the sidebar stays in place while the page scrolls, scrolling on its own when it is taller than the window.
- Agent push over SMB first: the Windows connector now installs over
\\host\ADMIN$and a temporary service (as PsExec and PDQ Deploy do) and uses WinRM only when port 445 is closed or the share is not usable. It follows the installer log, so a failed install reports its exit code, what it means and the last log lines (tokens redacted) within seconds, and it cleans up the MSI, the log and leftover push services. - A failed push now names its channel and step (for example open the service manager: access denied), and the AD computers list shows that message under the error, above the suggested fix.
Fixed after phase 6
- Live pages (devices, alerts, deployments, dashboard) could miss a change that happened while their live connection was opening, e.g. devices that enrolled right after the page loaded stayed hidden until the next change; the portal now refetches its live data whenever the connection opens.
- The Windows agent's inventory came back mostly empty (no last boot,
logged-on user, IP or MAC addresses, disks, network, services, updates
or local users): its PowerShell scripts were fed through stdin, where
statements spanning several lines are silently skipped. They are now
passed with
-EncodedCommand, and a script without output is reported as a collector error. - SMB pushes failed with open the service manager: access denied although the push account was an administrator: the service manager was opened as the connector's own account (the domain controller's computer account). The SMB steps now run as the push account.
- The site connector MSI never created its Windows service (two service
entries with the same name), so every install rolled back after
enrolling. It now installs one service, run as LocalSystem or the given
domain account, and sets restart-on-failure with
sc.exe. - Job results containing a NUL byte (for example an LDAP error from the connector) were rejected by PostgreSQL and lost, so Test connection reported "the connector did not answer in time". NUL bytes are now removed before the result is stored.
- Pushing the agent over WinRM failed on most computers with
copy_failed("copy exited 0", "checksum does not match") or a bogusauth_failed("invalid content type"): the MSI was sent on stdin while the WinRM client polled for output, which corrupted the encrypted HTTP stream. Commands now run one at a time in one shell, and the MSI is sent in chunks and decoded withcertutil. - A push downloaded the "latest" agent MSI but checked it against a hash computed earlier, so publishing a release during a push failed it with a checksum mismatch. Pushes now use the newest stable release's versioned MSI and recorded hash. Downloads are retried (4 attempts), and a DNS failure on the connector server names the host it cannot resolve.
- The agent MSI's verbose log showed the enrollment token in the enroll command line; the property is now hidden.
Security fixes (found in the phase 6 review)
- High: a technician's
silent_argsfor uninstall from inventory ran throughcmd.exeas SYSTEM, which allowed command injection. Only plain switches are accepted now. - High: a package uninstall by name could pick a per-user (HKCU) uninstall entry, which any Windows user can write, and run it as SYSTEM. Only machine-wide entries are used now.
- Medium: string parameters of
cmdscripts could inject commands through%RMM_PARAM_*%expansion. cmd metacharacters are refused now. - Medium: a revoked agent key stayed usable for up to 60 s on other replicas, and suspended tenants kept their open agent and connector connections.
- Medium: the agent MSI pushed by the connector was not hash-verified.
- Low:
- Uploads are always stored as
application/octet-stream. - Rejected uploads are deleted.
- The files host sends a sandbox CSP.
- CORS origins are validated.
- Presigned URL signatures are kept out of agent and connector errors.
- Undeliverable job payloads are no longer logged.
- The development example secrets are refused in production.
- Uploads are always stored as
- The EventSource access token no longer appears in URLs (stream tokens).
- Dependencies:
- Go toolchain pinned to go1.26.8 (standard library fixes).
moby/go-archiveupgraded to 0.3.0.- Caddy rebuilt with current dependencies.
Changed
- Axis no longer has pages for what Entrosity Hub manages: Tenants and Global admins (Admin), Users (tenant settings) and Account are gone; the menu under your name links to Manage account on Entrosity Hub.
- Entrosity Hub's product launcher greets you, shows your organization at the top and one card per product: the Entrosity mark, the product's name (product part in gray) and what it does, Access granted (or Suspended), your role and the organization. The whole card opens the product.
- Entrosity Axis has an Entrosity Hub button in its header that takes you back to the Hub's product launcher.
- Charts use the shadcn/ui chart component: the dashboard's operating systems donut, a device's CPU, memory and disk chart and its CPU temperature chart, and the agent and connector adoption charts. Their tooltips and legends follow the theme (light and dark) and show units.
- Everyone signs in on Entrosity Hub; Axis has no local sign-in any
more (migration 0013). Axis's passwords, sessions, two-factor secrets,
invitations, password resets and sign-in counters are gone: its
userstable is a copy of the Hub's users, and roles are intenant_memberships. Users, invitations, tenants (the Hub's organizations) and roles are managed on the Hub; Axis's Users, Global admins and Tenants pages are read-only lists with links to the Hub, and Account links to the Hub's account page. Old sign-in, password reset and invitation links forward to the Hub. Axis accepts only the Hub's product tokens;RMM_PLATFORM_URL,RMM_PLATFORM_INTERNAL_URLandRMM_PLATFORM_TOKENare required andRMM_AUTH_MODEis gone. Removed API:/auth/config,/auth/login,/auth/refresh,/auth/logout,/auth/password/*,/auth/totp*,/invitations/*, creating and deleting tenants, and creating, changing and deleting users and invitations; tenantPATCHtakes onlysettings. Deleting an enrollment token always takes a Hubstep_up_token.User/Melosttotp_enabledandlast_login_at, and the tenant dashboardpending_invitations. The error codeauth_movedand Axis's sign-in error codes no longer exist.rmm-server bootstrap-adminandmake bootstrap-adminare removed: the first admin is created on the Hub (platform-server bootstrap-admin,make bootstrap-platform-admin). Rolling back past migration 0013 means restoring a backup taken before it. - Axis moved from
/manageto/axis: the portal is athttps://<PLATFORM_DOMAIN>/axis/and its API at/axis/api/v1; new agents and connectors enroll withhttps://<PLATFORM_DOMAIN>/axis(the Hub's migration 0002 points the launcher there). Old/managelinks redirect; agents and connectors enrolled under/managekeep working. - Entrosity Hub moved to
hub.entrosity.com, with Axis athttps://hub.entrosity.com/axisand the documentation athttps://hub.entrosity.com/docs/.portal.entrosity.comandmanage.entrosity.comredirect browsers and keep serving the API for agents and connectors enrolled against them. Everyone signs in once more after the move. - The Hub always runs in the production stack.
PLATFORM_DOMAINand thePLATFORM_*secrets are required;COMPOSE_PROFILES=platformandRMM_EDGEare no longer used, andRMM_PUBLIC_URL,RMM_PORTAL_URLandRMM_CORS_ORIGINSdefault to the Hub's host. Caddy always serves the Hub's host, the old Axis host (RMM_DOMAIN) and the new optionalPLATFORM_OLD_DOMAINS(earlier Hub host names). The cutover script and workflow have one stage left,move <domain>, which moves the Hub to another host name (andstatus). make e2eruns the Axis and Hub Playwright suites against one stack (make e2e-hubis gone); the connector smoke test, the Windows nightly test,cmd/seed,cmd/apibenchand the k6 script sign in on the Hub.- The product is now called Entrosity Axis (formerly Entrosity RMM).
The new name appears in the portal (header, page title, sign-in and
invitation pages), e-mails (subjects, body and footer), the
documentation site, the API reference, the site connector's Windows
service display name and Add/Remove Programs entry, and the Grafana
dashboard. New two-factor enrollments show Entrosity Axis as the
issuer in authenticator apps; existing entries still say RMM and keep
working because the secrets do not change. Technical names are
intentionally unchanged so existing installations, agents and scripts
keep working:
RMM_*settings,rmm-agent.exe/rmm-connector.exe, theRMMAgent/RMMConnectorservices,%ProgramData%\RMMpaths,X-RMM-*headers, cookie names, metric names, thermmdatabase and roles, image and compose service names, MSI upgrade codes, Go module paths and the/docs/URL. - A user can belong to several tenants, with a different role in each
(migration 0012,
tenant_memberships). Permissions follow the role in the tenant being used; users of several tenants choose one after signing in and switch in the sidebar.GET /mereturnsis_global_adminandmembershipsinstead ofroleandtenant_id, and sign-in responses carry the same user. Alert e-mail preferences are per tenant:/me/notification-prefsmoved to/tenants/{id}/me/notification-prefs. The tenant setting "require two-factor authentication" was removed (it was never enforced; Entrosity Hub enforces it per organization). NewGET /auth/configreports the sign-in mode. - Sign-in on Entrosity Hub (prepared, off by default): with
RMM_AUTH_MODE=platformAxis accepts the platform's product tokens (RMM_PLATFORM_URL,RMM_PLATFORM_INTERNAL_URL,RMM_PLATFORM_TOKEN), keeps a copy of the platform's users, organizations and roles (pulled everyRMM_PLATFORM_SYNC_INTERVAL; metricrmm_platform_sync_age_seconds, alertRMMPlatformSyncStale), refuses sessions the platform ended, and answers the local sign-in and user-management endpoints with410 auth_moved. Deleting an enrollment token then takes a platform step-up token (step_up_token) instead of the password. The portal detects the mode (GET /auth/config): it then signs in and out on the Hub, renews its product token from the Hub's session, follows sign-outs in other tabs, and shows users, global admins, tenant names and account security read-only with links to the Hub. Local sign-in stays the default until the cutover. - Entrosity Hub in the production stack (off until enabled):
COMPOSE_PROFILES=platformruns the Hub's database, migration and service; backups, restores and upgrades include it; the deploy and release workflows build theplatform-backendimage. Caddy's sites are chosen withRMM_EDGE(rmm,hub,hub-only), which makes the move toportal.entrosity.coma settings change ([runbook]). Newdeploy/.env.prod.example;RMM_PUBLIC_URL,RMM_PORTAL_URLandRMM_CORS_ORIGINScan now be set indeploy/.env. - The portal moved to
/manage(step one of moving to the Entrosity Platform atportal.entrosity.com): the portal is served athttps://<domain>/manage/and its API, for the browser, at/manage/api/v1. The site root and old portal addresses (bookmarks, e-mailed invitation and reset links) redirect there./api/*keeps working for enrolled agents, connectors and scripts.RMM_PORTAL_URLnow includes the path (https://<domain>/manage); it also scopes the refresh cookie, so everyone signs in once more after the upgrade. GET /tenants/{id}/eventsaccepts?sse_token=fromPOST /auth/sse-token.?access_token=is no longer accepted. The portal handles this itself; custom clients must switch.- The public
/metricsroute was removed. Metrics are served onRMM_METRICS_ADDRonly. - Presigned upload targets always ask for
Content-Type: application/octet-stream.