Capabilities

What Helix NMS+ does today.

88 capabilities, every one of them built and reachable by a user. This page is generated from the product’s own feature catalogue, which is updated in the same commit as the change it describes.

Anything still in progress is deliberately not listed here. The catalogue tracks unfinished and unreachable work under separate statuses and this page publishes none of them — so a capability on this list is one you can use, not one that is planned.

Device management and monitoring

32

Multi-tenant device fleet

Routers grouped by organisation, with per-tenant isolation enforced at every route. 82 devices live.

Two connection modes

Reach a router over a direct public address or through a Helix-managed OpenVPN tunnel — for CPE behind NAT with no public IP. 63 of the fleet are tunnelled.

Zero-touch enrolment

A generated RouterOS script that a device runs once to join, bringing its own certificate and tunnel configuration.

Device analytics pane

The per-router analytics tab: CPU, memory and interface throughput over selectable time frames, with outages drawn as gaps.

Device tools pane

Ping, traceroute, bandwidth test and neighbour discovery, run from the router itself.

Device maintenance pane

Backups, firmware updates, configuration diff and scheduled upgrades for one router.

Live device dashboard

Ten panes per router: analytics, configuration, subscribers, tools, logs, Winbox, maintenance, console, WebFig, services.

Interface & system telemetry

CPU, memory and per-interface throughput on 1h / 24h / 48h / full-retention frames. Gaps render as gaps — a missing sample is never drawn as zero.

Port dashboard with optics

Per-port state, SFP vs copper, and optical transmit/receive power with thresholds.

Syslog ingestion & security events

A syslog server per deployment; failed and successful logins classified and weighted so an alert rule can match them. The banner names the weight of each line it lists, in words — only three groups are shown, so a header reading "2 critical" above three indistinguishable lines could not say which to act on. Each line also carries the SPAN it covers: the same count over six minutes and over a day are a brute-force burst and background scanning, RouterOS has no login lockout, and the rate is the signal. The span is a fact with no threshold applied, and a single event states none rather than "over 0s".

SNMP polling

60-second poll for system and interface counters. An unreadable value is recorded as unknown, never 0%.

Firmware update orchestration

Manual, scheduled and canary upgrades through one choke point that enforces downgrade blocking, version pins, minimums and patch-only mode.

Low-flash pre-flight

Refuses an upgrade a device has no room for, and says what to do instead — measured against real image sizes per architecture.

Configuration backup & diff

Scheduled and on-demand backups over FTP, with a readable diff between versions.

Configuration baselines

Declare intended NTP, DNS and logging state and reconcile devices toward it.

Platform operations console

Every operation across every tenant for the super-admin, filterable by state — who asked for it, what the subject was, and what the device said. An operation with no actor reads as "unattributed" rather than being given an invented one, and the empty state admits the ledger is not yet a complete record.

My operations (profile)

A person's own operation history in their profile, spanning every organisation they work in — because a person is not a tenant. Self-scoped by the session, never a query parameter. States the 7-day window, so "nothing this week" is not read as "nothing ever".

Device operations console

Every operation Helix performed on a router — what was attempted, by whom, and whether the device confirmed it — with the 7-day window stated in the response so an empty month reads as retention rather than silence. Currently fed by eight paths — a figure DERIVED from the tree and pinned by a rising floor rather than claimed. Seven are device-facing (backups, commands, updates, subscription provisioning, device onboarding, service enforcement and interactive Winbox sessions); the eighth is the first that is not — a Splynx migration, which writes a whole ISP's customers and subscriptions and has no device at all. It could not appear here until the ledger stopped being device-only, and it is the operation an operator most wants to watch: the longest-running and least reversible thing the product does. A session whose router is unreachable is PARKED rather than reported finished, and the queue drain closes it. Two remaining paths are deliberately absent and say why: one runs 149 times a day and would drown the console, the other has an empty working set. The 7-day window is now enforced by the nightly purge, not only stated — and an operation still unfinished past it is counted separately, because a row that opened and never closed is a defect rather than a tidy-up.

Provisioning queue

Every RouterOS action that could not run immediately, retried per device IN ORDER so a change made while a router was unreachable is not lost. The two waits are different and the console now shows which one a task is in. A device that is REACHABLE but rejects the work backs off exponentially and dead-letters after five attempts. A device that is OFFLINE is not an attempt at all: nothing is counted, nothing expires, and the task simply waits — shown as ELIGIBLE NOW beside the router status — because these tasks are desired state rather than a point-in-time command, so running one on the device's return is the point. Each row names when it was last attempted, or NEVER ATTEMPTED.

Configuration baseline apply

Push a baseline template to selected routers. Devices that are offline, or whose apply does not land, are QUEUED and retried when they come back rather than being reported as done — and the response says per device what actually happened, with the batch verdict false if any one of them did not land. Bounded to four routers at a time, because the API session cap is shared with the operator’s own Winbox.

Orphaned port-forward teardowns

/api/health names every port-forward removal Helix gave up on — device and rule id — and states what it means: an inbound NAT rule is very likely still live on that router while the product believes the forward is gone. A database query costing no RouterOS sessions, because the failed task already names both. It reports; it does not remove. Measured 2026-09-03: zero dead-lettered port-forward teardowns on production, so this reports a measured clean rather than an unlooked-at one — the probe defaults to unavailable, never to 0.

Busiest port per device

For every router, the single busiest port it has — never an average across its ports, because one saturated uplink beside twenty-three idle access ports averages to a comfortable number and hides the only one that matters. The percentage always carries the link rate it is a percentage OF, since a gigabit port that negotiated 100 Mbps looks half idle otherwise. A router whose ports cannot be judged at all is left out and counted, and the pane says that is not the same as idle. Read from polled state; no router is dialled.

Abandoned device actions

/api/health reports every queued device action that will not run without intervention, grouped by state, action and device so nineteen failures on two routers are two lines rather than nineteen. The count is always shown and the ALARM fires only on growth — a field that stays red until a months-old backlog is cleared is one people learn to ignore, and this deployment has watched that happen on an alert channel. The two terminal states are kept apart because their remedies differ: FAILED is fixable here (an unknown action, a deleted device), DEAD_LETTER means the router was reachable and refused the work repeatedly. Costs no RouterOS session. Measured 2026-09-03: 17 FAILED and 19 DEAD_LETTER on production, oldest 113 days, none newly terminal — so it will report a visible backlog and a quiet alarm, which is the intended reading.

Double-billing exposure

While an ISP is still collecting in its old system, Helix can invoice the same service twice. /api/health reports how many subscriptions are in that state and names the ones newly billed by their id in the OTHER system, because that is the row an operator has to go and stop. It counts DEMANDS only — invoices Helix minted to record a payment collected elsewhere are receipts, not double bills, and they are the majority — and it identifies them by the absence of that payment rather than by unpaid status, so a subscriber who pays both bills stays counted instead of vanishing at the moment the harm completes. The alarm fires on new bills, not on the standing total. Measured 2026-09-03: 169 exposed, 6 demands, 1 today.

Recovery pin (online drains its own work)

A router coming back ONLINE immediately drains its own queued actions and clears its own pending enforcement markers, instead of waiting up to 60 seconds for the fleet sweep and up to 15 minutes for the dunning tick. Bounded to three concurrent recoveries, because max-sessions is 20 and shared with the operator's own Winbox — a pin that stampedes is worse than the timer it replaces. The timers stay as the backstop: an event can be lost to a restart, and the sweep is what makes that survivable. OFFLINE deliberately triggers nothing. Measured 2026-09-03: the Postgres trigger that emits the events is installed and enabled on production, but the pin has never observed a real transition — `monitoring-service` must be restarted for it to run at all, and `[RecoveryPin] listening on device_events` in its log is the only evidence it took.

Bulk & mass operations

Fleet-wide command execution and mass firmware updates with bounded concurrency, because a router's session budget is shared with the operator's own Winbox.

Winbox tunnelling

A time-limited port forward so an operator can reach Winbox on a tunnelled router.

Web terminal & WebFig proxy

Browser console and a proxied WebFig for devices with no direct route.

IPAM — disposition worklist

Accept or dismiss a discovered address that no assignment accounts for. Accepting records that the observation is real and ours — it does NOT create an assignment, because a route comment names the ROUTE rather than the client behind it, and two of three such comments on the Boss Telecom BNG disagree with the operator's own client list. The decision stamps who and when on the finding itself. Re-opening a decided finding is refused rather than silently ignored. Before this existed, status, decidedAt and decidedById had no writer anywhere and every finding stayed PROPOSED for ever. It opens on its empty state today: the findings table does not exist on production (branch-only migration), so the 105 from the first run were reported and never stored.

IPAM — ICMP liveness

Which assigned addresses are answering — now visible in the product, as an *Answering ICMP* column on the host-assignment table with its coverage stated above it (2026-09-06; until then the store had no reader anywhere and the reading reached no human). A stored reading is not a live one: anything older than 24h reports as *last checked N days ago* rather than rendering green, because a three-week-old RESPONDING looks exactly like a fresh one and is worth less the greener it looks. As part of the discovery report. Zero router sessions — public addresses are pinged from the Helix host, so the session budget (20, shared with the operator's Winbox) is untouched. Four honest states: RESPONDING, SILENT, UNMEASURABLE (private space, which needs a probe on the owning router) and UNKNOWN (not probed). Silence is never reported as "down" — a firewall dropping ping is a working service — and the responding percentage is taken over the addresses actually PROBED, never the total. First production run 2026-09-06 across Boss Telecom: 51 host addresses, 45 responding, 88% — a REPORT; `IpReachabilityProbe` does not exist on production yet (branch-only migration), so no reading has been stored and the new column reads *not probed* for every address until the branch merges and somebody runs the sweep with --persist.

VPN outbound routes

Per-organisation outbound routing over the tunnel, with Helix-owned objects tagged so removal can never touch an operator's own rules.

Tunnel management

Tunnel status, client certificates and per-device tunnel addresses, across two OpenVPN planes — a primary and a second one carrying the RouterOS v6 devices, whose client cannot speak the primary's cipher.

Alerting and incident response

9

Alert rules & channels

Per-organisation rules matched against device and syslog events, delivered to in-app and email channels.

Role-based alert routing

Who hears about what, and how often, decided by ROLE rather than by one shared address. Six categories against six roles: an operator is paged about a router immediately, a business owner gets a weekly summary of the same thing, a finance admin never sees it, and a critical event reaches everyone accountable at once. A person can override their own cadence per category from their profile, and the role default is always shown beside their choice.

Alert digests

Daily and weekly summaries for whoever is accountable for something but does not need interrupting. Devices are named rather than counted, an undelivered summary is retried rather than dropped, and a summary abandoned as stale says so instead of vanishing.

Incident console

Open incidents, acknowledge individually or in bulk. A refused acknowledgement never repaints as success.

Escalation ladder

Unacknowledged incidents climb on a timer.

Alert coalescing

A correlated storm becomes one summary rather than 49 notifications; the first event still goes out immediately.

Repeating-condition alerts

A failure that is still true is not news. A device whose backup keeps failing is reported when it starts failing and then restated once a day, rather than on every retry — measured before the change at four critical emails a day about one router, which is what made an operator switch their email alerts off entirely. It is keyed per DEVICE, so one router failing never silences another, and it never falls fully silent: the daily restatement means a device broken for a week does not quietly vanish from its own alert channel. Opt-in per event type, so nothing an operator relies on was quietened without a measurement behind it.

Offline damping

A device must be down five minutes before it pages — derived from a measured bimodal outage distribution. The transition is always recorded even when the page is withheld.

Health endpoint

/api/health reports release, database, CRL, OpenVPN planes and cron outcomes — with an outcome axis beside freshness, so a job failing every cycle cannot read as healthy.

Billing and ISP operations

15

Plans and tariffs

Priced service plans per organisation, in the organisation's own currency. The service type may be PPPoE, Hotspot, Static IP or Dedicated VLAN — the last added 2026-09-07, because a dedicated-VLAN business client could not be given a correctly-typed plan from any form. Plan creation itself was impossible until 2026-09-07: both forms posted their numeric fields as strings against a numeric schema, so every save failed — which is why Boss Telecom had zero plans.

Customers & Customer 360

A customer record with services, invoices, payments, wallet and contacts on one page.

Subscriptions

AND THE DEDICATED FORM THREW THE OPERATOR'S GATEWAY ADDRESS AWAY UNTIL 2026-09-08. The block renders a *"Client gateway address"* field bound to subForm.staticIp — and the payload sent staticIp only for STATIC_IP, so a dedicated business client was provisioned with an UNADDRESSED VLAN, provisioned stayed true (the executor's address step is if (p.ipAddress) with no else) and the toast reported success. A dedicated link with no address carries nothing. Worse than a missing field, which an operator can SEE: this one was collected, hinted and discarded, and the hint promised a per-IP shaping queue the payload could not create. Everything else already existed — the field, the state, the route, the planner — so the fix is one spread line, and the guard beside it compares, per service type, what the form COLLECTS against what it SENDS, which nothing did. CORRECTED FROM `INERT` 2026-09-08, against production: SOMOTT holds 303 subscriptions, 169 of them ACTIVE, behind 76 invoices of which 57 are PAID. INERT means reachable-with-no-data and that has not been true since the Splynx APPLY completed on 2026-08-31; the row simply was not moved. Found by a guard on the PUBLIC marketing site — helixnms.com calls billing "Available now" and the census refused it, which sent me to production rather than to the copy. PPPoE, static IP, DHCP-reservation, hotspot and dedicated-VLAN subscriptions, provisioned onto the router at creation. Device-first: a subscription is not marked active until the router confirms — and since 2026-09-07 that holds for a CPE_STATIC client too, whose shaping queue is its only device object and its usage-accounting source. Before then nothing derived its status: the row went active and was invoiced whether or not any queue reached the router. A DHCP-reservation client still takes its status from the lease, so a queue-less active client remains possible there and is recorded in the cutover runbook.

Receivables list (who owes money)

*"Who owes me money"* across BOTH open statuses at /admin/finance/receivables — dunning flips UNPAID to OVERDUE every fifteen minutes, so a single-status filter returns half an answer and omits exactly the debt at risk of disconnection. Oldest-due first, so the 200-row cap keeps the longest-outstanding rather than the newest, and the page says when it truncated instead of letting a cut list look like a whole book. A total is refused rather than invented when the rows span currencies. Measured 2026-09-01: the live Somali tenant holds 34 invoices (31 PAID, 3 UNPAID raised that day in USD, due 2026-09-08), so this returns real rows. Not on production yet — it reaches it on the next deploy.

Deliverability console

*Which subscribers were not reached, and why* — at /dashboard/billing/deliverability. NotificationLog has recorded the reason every message failed to land since it was written, and nothing read it: the one query that fetched it returned it under a key no component consumed, and did not even select the reason field. Five situations were collapsed into one SUPPRESSED badge — *coalescing into a summary* (fine), *no email on record* (the subscriber cannot be reached), *no SMS channel configured for org* (the ISP has not set it up), *opted out*, *quiet hours* — each with a different remedy. Now grouped by classified reason, with the affected subscribers NAMED and the action stated, and only the three classes anyone can act on are listed. A failed read denies being an all-clear rather than rendering as "everyone was reached". Measured 2026-09-02 on the live Somali tenant: 394 of 395 customers have only a phone and no SMS channel is configured, so every invoice reaches them in-app only — this is the pane that says so.

Cash desk (cashdesk)

Over-the-counter payment capture for an ISP collecting cash — the teller takes money, the subscription reactivates optimistically and the router is reconciled after, because a teller who sees "still suspended" takes the money twice. A shift is one drawer belonging to one teller (S-212, 2026-09-03): a teller holds at most one open shift, payments post to their OWN, and the till offers to open one rather than adopting a colleague’s. Two counters at once is supported and is the point of keying on the teller rather than the org. The closing variance (counted minus expected) is shown after a close (S-213) — it was computed and rendered by nothing before — and a tender shortfall is named as one rather than as "change due" (S-214). And when the router does not confirm the reconnection the till SAYS so (S-215), rather than reporting the payment as done full stop — the subscriber is at the counter asking whether their line is back. NEVER USED IN ANGER — zero shifts have ever been opened on production, so every claim here is from tests.

Bank statement reconciliation

Paste a statement, see exactly what matched before anything is written.

Magic-link subscriber access

A subscriber reaches their own portal from an emailed link, with no account to create.

Scheduled-job console (crons)

Every scheduled job with its last run, outcome and degraded state — so a job that ran but partly failed cannot read as healthy.

Credit notes & outage compensation

Credits, and automatic compensation for observed outages — which withholds rather than crediting when no policy is set.

Vouchers

Prepaid access vouchers.

Reseller & wholesale settlement

Two-party revenue share with statements, disputes and settlement.

Shaping queues view

The simple and tree queues a router is enforcing, per subscriber, so a rate limit can be read against the plan that was sold.

Traffic vs subscribed capacity

Per-subscriber throughput against the plan's ceiling, with the threshold drawn only where the router actually enforces one.

Tickets & CSAT

Support tickets with satisfaction scoring.

Splynx migration and coexistence

10

Splynx connector

Read customers, services and tariffs from a live Splynx instance.

Dry-run migration

See exactly what would be created, per record, with a reason on every skip — before anything is written.

Plan catalogue import

Bring a tenant's Splynx tariffs across as Helix billing plans — on their own, naming a subset if the migration splits by access method. Creates no customers and no subscriptions, and re-running is safe. Previewable: a plans-only dry run touches one endpoint and returns in seconds, where a full dry run of a 3,500-customer tenant takes minutes and reports on subscriptions they are not importing yet.

Tariff catalogue and split picker

See every Splynx internet tariff — id, title, price, down/up — and mark each as *only* or *excluded* for the next run, instead of typing ids into a text box. The subset is how a tenant whose clients split across access methods runs the migration twice (corporates static, residential PPPoE), and a mistyped id does not error: it imports a residential plan as static. A tariff can never be in both lists. An unstated price or rate renders as a dash, never a zero.

Tariff-scoped runs

Restrict a migration to named tariffs, or keep named tariffs out of it. A tenant whose clients split across PPPoE and static needs two runs, and each stays out of the other's catalogue.

Observed placement

Binds each subscriber to the router that actually carries them, from live sessions and queues — never from Splynx's own router grouping, which measured wrong on both live tenants. Refuses rather than guessing.

Coexistence modes

OBSERVE / COEXIST / OWN. While an ISP still runs its old system, Helix will not cut a subscriber the other system is still collecting from.

Double-billing detection

Names, per run, any subscriber both systems would invoice.

Payment sync

Import Splynx payments hourly so dunning never suspends someone who has already paid.

Cohort import

Check and import a migration cohort in batches, with every problem located by line. Since 2026-09-06 it can also ask the ROUTERS — an opt-in pre-flight that reads each target device once (one session per router, never per row, against a max-sessions of 20 shared with the operator's Winbox) and reports per line whether the address is already leased to another MAC, already shaped by a queue this platform does not own, or aimed at a router with no DHCP server. That ownership test was COMMENT-ONLY until 2026-09-07 and could never recognise a Helix queueupsertSimpleQueue has never written a comment, and 0 of 1,603 queues on the fleet carry one — so its *"re-running is safe"* branch was unreachable and a re-run after provisioning reported Helix's own queue as a conflict to resolve on the router. Ownership is now the helix-<username> NAME (which every existing queue already has) as well as the comment, and the queue is comment-tagged per §A like every other Helix-owned device object. And the same warning now fires at SUBSCRIPTION CREATION too, because a client added by hand through Customer 360 never reaches this pre-flight — the most likely way to create BT's first corporate subscription was the one way that got no warning. A router that could not be read is `UNVERIFIABLE` and is counted in its own column, never as clear. A routed address and a stale ARP entry are warnings rather than refusals, because both are the normal case for a corporate client on a routed /31. Writes nothing, to the database or to any device. AND THE FILE IT GENERATES CAN NOW BE READ BACK BY THE CHECKER — measured 2026-09-08, it could not. The generator escapes a quote the way CSV requires (""); the parser dropped it instead of un-escaping it, so a tariff whose title contains a quote round-tripped to a DIFFERENT name and the row failed with *"tariff not found"* — one row of sixty, silently, which is harder to spot than the whole file failing. The same census found three other CSV exports (admin logs, billing payments, IPAM blocks) quoting every cell and escaping none, so a customer named ACME "Fibre" Ltd shifted every later column of its row under the wrong header in the operator's spreadsheet; and the log export additionally REWROTE the message, replacing commas with semicolons it had already quoted against. One writer and one reader now, side by side. The file can be generated from Splynx rather than typed — which matters because a hand-typed row is a hand-typed IP address, and that address is written onto a live router at cutover. A client no device has seen is still in the file, with the router column blank and the client named: nothing guesses at a device, and the check refuses a blank router by line, so the row cannot be imported until a human names one. Those rows are reported separately from ones that could not be generated at all — the two need different actions, and being told “skipped” about a client already in your file sends you back to the wrong system. The check also warns when a cohort address is already recorded against a PPPoE login, because the two import paths key a subscription on different columns — the cohort on the address, a Splynx import on the login — so the database constraint cannot see that duplicate and both subscriptions would be invoiced. That warning does NOT block the import and says so, since a login address is where the subscriber was last seen rather than one we assigned, and pool addresses are reassigned.

Access control, audit and multi-tenancy

8

Organisations & memberships

Owner, admin, finance-admin, member and client roles.

User management

Invite, suspend and re-role members of an organisation; a refused change never repaints as success.

Organisation settings

Branding, timezone, maintenance window, update policy, retention tier and alerting defaults.

Tenant isolation

Enforced per handler and measured by a contract suite that drives every route as an outsider, not by review.

Audit trail

Append-only record of configuration intent and outcome, authorisation denials, and money events — with a console to read it.

Finance scope separation

"May you see the console" and "which organisation is this about" are distinct questions with distinct guards.

API keys

Scoped keys with expiry ceilings, minted deliberately rather than as a side effect.

Credential encryption

Device and tunnel secrets encrypted at rest, with key rotation.

Platform operations

14

Pull-based deployment

The server polls and deploys; CI only observes. One deploy path, with a circuit breaker and a rollback pin.

Scheduled jobs

18 cron jobs with heartbeats, and a degraded axis so a job that ran but partly failed cannot report healthy.

Project tasks tracker

The reviewed sprint backlog in the super-admin console — operator decisions, work in hand and deliberate non-decisions, read from the committed file at the deployed release so there is no second copy to disagree with the repository. Shows its own review freshness, and a stale review says what that means: closed items may still be listed and new ones are missing.

Retention

Per-plan retention for SLA metrics and logs, deleted in bounded batches.

Backup console

The super-admin view of whether the database is actually being backed up: per-mode state, run counts and failure reasons over 15 days, typical size and duration, what the dumps cost on disk, and a live view of a dump in flight. Progress is measured from the file being written, carries what it is measured against, and shows no percentage at all when there is nothing comparable to measure against. The last-run age carries the schedule that makes it comparable — "30h ago" is alarming against a six-hour cadence and unremarkable against a weekly one. Stated as the cadence and never as the alarm boundary (stale is twice the interval, and restating that here would be two writers of one policy); a mode with no configured interval shows none rather than inventing one.

Emergency backup

Take a dump now, from the console. Runs the same script the timers run, in its own mode so it cannot reset a scheduled backup's freshness clock, and refuses while another dump is running.

Backup event log

15 days of backup events — started, succeeded, failed with its reason, skipped, pruned — kept on disk rather than in the database, because a backup exists for database disasters and a dump that failed because the database was unreachable must still be able to say so. Self-pruning, and a corrupt record is kept and reported rather than silently dropped.

MikroTik news & product feed

MikroTik product announcements and release notes surfaced per organisation, so an operator sees relevant vendor news without leaving the console.

Fleet service exposure

Which routers offer Winbox, the API, SSH or the web console to any address — and which still have the cleartext login protocols, telnet and FTP, switched on at all. All eight of a RouterOS device’s configurable services are covered, and the two cleartext ones are judged differently on purpose: an address restriction narrows who can read a password sent in the clear without stopping it being readable, so for those the finding is that they are enabled, not that they are open. Read from the nightly hardware sync rather than by contacting a device. Internet-facing routers are listed first and counted apart from tunnel-facing ones, because a DIRECT box’s open port and a tunnelled one’s are not the same finding — and on this fleet nearly every router carries something, so without that ordering the handful reachable from the internet would sit among dozens that are not. Nothing is hidden by it: the tunnel-facing findings are still listed and still counted. Devices and findings are reported as separate numbers — one router can carry one finding per check. A router the sync has not reached is reported as unread, never as clean, and every row states how old its reading is, so a narrowing that has not yet been re-read does not look like a narrowing that failed. It offers no fix: changing /ip/service on a live fleet is a maintenance-window act.

Public privacy notice & terms

/privacy and /terms on the product site, in the sitemap and linked from every page's footer. They exist because Google's OAuth consent screen will not let an app leave Testing without both URLs resolving on an authorized domain, and they are written from what the code measurably does rather than from a template: the analytics ID and cookie domain, the exact account fields, that the password is stored only as a hash, that a Google identity is not auto-linked to a local account with the same email, and the real 7/30/45-day log and 3/7/15-day metric retention windows. The load-bearing distinction is stated first — Helix is the CONTROLLER for its own accounts and this website, and a PROCESSOR for the subscriber records it holds for an ISP — so a subscriber is routed to their provider instead of being answered for. What they deliberately do NOT claim is the careful part: no breach-notification deadline (ADR-0002 is unsigned), no lawful-basis assertion per subscriber scope (ADR-0005 is unsigned and explicitly does not decide it), no ODPC registration and no named DPO, because neither was verified — an unverified compliance claim on a privacy page is worse than an absent one. The terms say plainly that the software writes configuration to live routers and can cut a subscriber's service, and that the product is pre-GA with no availability level promised, because there is no SLA document to point at. A signed customer agreement outranks the page and it says so. Pinned by helixnms-seo-census.test.ts: both routes exist, both are in the sitemap (not footer-only), the footer renders them on every page, and the "last updated" date is a written literal that cannot be computed from the build — the defect the sitemap's lastModified was removed for. NOT DEPLOYED, so both URLs 404 today and Google cannot verify them until the site is live; and they have not been reviewed by a lawyer.

Console public overview

/overview on the console host — a short public orientation for somebody who reached cloud.helixnms.com directly rather than through the product site, with every claim linking out to helixnms.com and its documentation. Reachable from a global footer nav that renders LOGGED OUT (verified by rendering the login page), which is what stops it being the built-but-unreachable class this catalogue records repeatedly; the page-reachability census confirms it is not an orphan and the ceiling of 9 did not move. It carries no numbers, deliberately — the marketing site generates its figures from this catalogue at build time, and a second copy here would have no generator behind it and would drift. Not indexed, by operator decision: cloud.helixnms.com is noindex/disallow-all, so the two hosts never compete for the same search terms and /portal/* stays out of every index.

Sign-in modal

The console's "Sign in" controls — the sticky public header and both landing-page CTAs — open a dialog over the page rather than leaving it, with the credential form, Google sign-in, create-account and reset-password reachable inside it by switching views. It hosts the existing forms and reimplements none of them: the credentials provider deliberately collapses unknown-email, wrong-password and no-local-password into one answer so an anonymous caller cannot enumerate accounts, and a second sign-in form would be a second place for that to drift. A native <dialog> supplies the focus trap, Escape and top-layer stacking; the panel is unmounted on close so a typed password does not survive in a closed dialog. Every trigger and every in-dialog link is a real `<a href>` to a page that still exists — no JavaScript, a failed hydration, a crawler and a middle-click all get /login, /register or /forgot-password — and the link to /reset-password is deliberately never intercepted, because it carries an emailed token. Verified by rendering: 16 tests, and a tree-derived guard that refuses a raw anchor to any auth route inside any auth form.

Signed-in awareness on the product site

A visitor who arrives on helixnms.com holding a live console session sees "Go to dashboard" instead of "Console" (operator directive 2026-09-08). The product site is a static export on another origin, so it asks the console — one credentialed fetch to GET /api/auth/presence, which answers a single boolean and nothing else, with CORS scoped to exactly the product site's origin, Vary: Origin and no-store. The cookie travels because the two hosts are one SITE (helixnms.comcloud.helixnms.com); from the legacy origin it is not sent and the answer is "not signed in", which is correct there. It fails towards "Console": the exported HTML says "Console", and only a confirmed true upgrades it — a refused CORS, a dead console or a non-JSON body leave the default. Inert until the console is served from `cloud.helixnms.com`, because the session cookie is host-only and the current origin is a different site.

Releases & advisories

MikroTik release and CVE advisory tracking, per-organisation digests, and a fleet view of which devices a given advisory affects.