What's New
This manual documents QUBIQ 1.0.7. Capabilities that arrived during the 1.0 series carry a badge like this one New in 1.0.7 on the page that describes them, so you can tell at a glance whether something is available on the version you are running.
1.0.7
A tag that has no value yet says so, and says why. Changed in 1.0.7 A read
used to answer NotFound for two different things: a name that matches no tag, and a real tag that
simply has no value yet. That is the same word a typo produces, so people went looking for a
misspelled path when the tag was right there. A tag that exists now reads Unknown, with the
reason: bound but not reported yet, no enabled binding, or not evaluated yet. Scripts, the AI
assistant and the Industrial I/O node all get the same answer. Those last two also stop reporting
internal and expression tags as missing. Until now every such read from a pipeline or the
assistant came back empty, whatever value the tag held.
→ A tag with no value yet
An initial value you can see, and one that fits its type. Changed in 1.0.7
Creating an internal tag now fills in Initial Value with its type's default. It used to be a
blank box that the server quietly filled in later. The value must fit the type: 300 in a byte
tag is refused rather than wrapped to 44, and invalid JSON is refused rather than stored as text.
Before, a typo in a number box silently became 0.
→ Initial value
UDT members can be computed, and each one reads its own instance. New in 1.0.7 A member
can now be an expression tag. {InstancePath} points it at its own instance, so
tag["{InstancePath}/Sensors/Speed"] reads Ship1's speed in Ship1 and Ship2's in Ship2. A path
typed literally would have every instance computing from the same tag. The Expression tab's
This instance picker lists every tag an instance will hold, so you don't have to type the
paths.
→ Computed members
Sync all. New in 1.0.7 Sync all (N) brings every out-of-date instance, of every type, back in line in one action. Before, a type edit that touched a dozen instances meant a dozen dialogs. It runs as a background job with visible progress. An instance that fails is left untouched and still flagged, so Try again finishes exactly the remaining work. Each run is written to the audit journal. Renaming a type, or saving one unchanged, no longer marks every instance out of date for a sync with nothing to do. → Sync all
A Sparkplug edge node can say which PLC died. New in 1.0.7 A Sparkplug publisher used to
put every tag on the edge node, so the only death a host could see was NDEATH, meaning the whole
gateway had gone. When one PLC behind QUBIQ dropped, its tags just stopped changing, which looks the
same as a process standing still. Devices → One per source connection gives every connection that
feeds the publisher its own Sparkplug device, with its own DBIRTH, DDATA and DDEATH. A device
dies when its connection fails, not when it is merely quiet. The option previews the devices the
publisher will produce, by the ids they will have on the broker.
→ Devices
A compliant Sparkplug host had to discard what QUBIQ published. NBIRTH and NDATA went out retained, at QoS 1, which the specification forbids, so the broker kept serving a dead session's birth to every new subscriber. A reconnect resumed data against an alias table the host had already thrown away, and an orderly stop sent no death at all. After upgrading, every Sparkplug publisher is not-retained at QoS 0, and Never miss a value is refused for Sparkplug. QUBIQ does not clear births already retained on the broker; clear them with your broker's tooling.
Four value shapes were also wrong on the wire, and the same tag now publishes something different.
A Boolean fed by an integer source was always false, a DateTime given as text was dated 1970, and
JSON and byte values were unreadable.
→ What a Sparkplug publisher does not let you choose ·
Values that went out wrong
One bit of a Modbus register, and Modbus strings. New in 1.0.7 HR:100.3 addresses bit 3
of a holding register. A write to it uses Mask Write Register (function code 22), so the device
changes that one bit atomically and the other fifteen are untouched. Before, there was no way to
name a bit, so a Boolean bound to a status word read true whenever any of its bits was set. That
is still what a Boolean on a whole register means, so check any you have. A string tag can now
bind to Modbus: ASCII, two characters per register.
→ One bit of a register · Strings
One dead device no longer stalls the rest of its protocol. Changed in 1.0.7 The Modbus, SNMP, TCP/UDP, S7 and EtherNet/IP workers handled most requests one at a time, across every connection. A read, or a 60-second SNMP walk, against one unreachable device held up every other device of that protocol, and callers were told worker unavailable about a healthy worker. Requests for different connections now run side by side. EtherNet/IP keepalives no longer queue behind a hung controller, which used to cost healthy controllers their sessions. → One dead device is one dead connection
Values that looked right and were not. Changed in 1.0.7
- TCP/UDP published the fragment of a message cut short as a Good reading. It now refuses it. One side effect: a device that sends its last message without the delimiter and then closes the connection now loses that message.
- Siemens S7: when the CPU refused a whole request, the badge stayed green while an entire scan group went permanently blank. Those tags now go Bad with the reason.
- Modbus: a reply that arrived just after its timeout forced a reconnect. It is now recognised and discarded, and the socket is kept.
→ TCP/UDP · Siemens S7
A node says whether its connection is up. New in 1.0.7 Every node bound to a connection carries a status marker and a caption under the card, such as connected, receiving · 12 in · 5 out, retrying, no recent data or disabled. Before, a pipeline full of nodes bound to a dead device looked exactly like one that was working. It was worst for a trigger node, where "the connection is down" and "nobody has sent anything" both showed as a blank card. → The connection status under a node
Disable means disabled. Changed in 1.0.7 Switching a connection off now stops the pipeline nodes that use it: SQL Query, MongoDB, QuestDB, Send Email, Telegram and WhatsApp. Each fails with an error naming the connection. The toggle used to reach only the data path, so a disabled SMTP connection went on sending mail, and a disabled Telegram bot went on being polled. A connection can also now be created disabled; saving a new one with the toggle off used to store it enabled. → A node on a disabled connection fails
Telegram: the message that sometimes never arrived. Changed in 1.0.7 Telegram hands a bot's messages to exactly one poller per token, so two installations sharing a token each received some of them. Both still said connected, because the status only checked that the token was valid. It now reports what the gateway actually observes, including Another instance is polling this bot token. In that case the gateway waits five minutes instead of knocking the other installation off twelve times a minute. → One bot token, one installation
A colon in a string or a comment is no longer a parameter. Changed in 1.0.7
Saved queries read every : as the start of a named parameter. That caught 'HH24:MI:SS',
-- shift starts 09:30 and ::text casts. It rarely failed loudly: the database received a
different statement and returned the wrong number of rows with no error. The binder now follows
each engine's own rules for strings and comments.
→ Colons in strings and comments
Every saved-query parameter is required, and Means does what it shows.
Changed in 1.0.7 The Req tick box never did what it said. The statement
contains :shift literally, so an "optional" parameter could only ever be passed empty. The column
is gone. Means is checked when you save, and Point in time now resolves; before, it was
never read. A missing parameter is now reported to the assistant, so it can fill the gap instead of
retrying.
→ Declared parameters
The WYSIWYG component is a WYSIWYG editor. Changed in 1.0.7 It was a split-pane Markdown source editor, so the name promised something it could not do. It now edits formatted text directly, and the stored value is still plain Markdown, so every binding and form that reads it is unaffected. Selecting text brings up a formatting bubble, and table cells can be merged and split. The source and preview modes remain. They are the way to keep inline HTML as it is, because rich editing converts it to Markdown; the editor warns before doing so. → WYSIWYG
A Scheduler bound to a query works, and writes back. Changed in 1.0.7 A board
whose events came from a named query sat on Loading data… indefinitely. Once it did render, the
first drag replaced the binding with a frozen copy of the query's result, so the board silently
stopped following the database. A bound board now renders, and a drag leaves the binding alone and
fires eventChange for you to save. The Scheduler page now covers the whole round trip: the
queries, the update script for a drag or resize, and an insert script for a click on empty
timeline.
→ Driving the board from a database
A Scheduler that opens on today. New in 1.0.7 rangeStart and rangeEnd accept times
relative to the clock, such as now-2h, today and today+5d, so a live board no longer has to be
re-dated every morning. preventOverlap, off by default, stops a drag or resize from landing one
block on another in the same row. Dependency arrows now follow a block while it is dragged.
→ A window relative to now
A theme-locked view stays readable. Changed in 1.0.7 Some components kept the surrounding theme's text and surface colours inside a view locked to a fixed palette. The result was dark text on a dark background on an operator screen, with nothing logged. Every component now follows the lock. → Locking a view's theme
The audit journal's filters search the whole journal. Changed in 1.0.7 Origin, category and search used to apply only to the page already loaded, so a record two pages back was simply not found. That is a dangerous answer from the place people go to establish what happened. Filtering is now done on the server. The pager gains a page size, a jump to the newest events and a clear end of journal. → Reading the journal
A backup says what it will cost, and a large one can be restored. Changed in 1.0.7 Include File Manager & uploaded files now shows its size before you download anything. A restore used to be capped at 512 MB and held in memory while an export had no limit, so an instance could produce a nightly backup it could not restore. An unencrypted archive now restores up to 4 GB, read from disk. An encrypted one keeps the 512 MB limit, because it has to be authenticated whole, and a larger one is refused with the reason. → How large an archive can be restored
A storage folder cannot be a database's. New in 1.0.7 An uploads or library folder that holds PostgreSQL, MongoDB, MySQL, QuestDB, Redis, InfluxDB or Elasticsearch data is refused. The refusal names the product and the file that gave it away. On one installation the uploads folder was the parent of its Docker database volumes: media backups archived live database files, and the File Manager offered to rename and delete them. → Storage folders
The assistant knows where a value comes from. New in 1.0.7 Reading a tag now tells it whether the tag is a device, internal or expression tag, and for an expression tag, the formula and the tags it reads. Before, it described a computed number as though a sensor had produced it. → AI assistant
Also in 1.0.7: the Reporting module and its licence entry were removed from the product. This manual had already stopped documenting it.
Fixes worth knowing about:
- Copied tags: a copied tag keeps its write level. It used to reset to 0, which made a copy of an admin-only tag writable by anyone. A copied internal tag also stays internal.
- Publish mode: editing an existing tag's publish mode now saves.
- Deleted folders: deleting a folder removes the expressions of the computed tags under it. They used to keep running unseen in the engine.
- UDT connection parameters: a UDT connection parameter now lists connections, where it used to always say No connections available.
- Clearable fields:
clearableworks on number and password fields, where it saved but drew nothing. - Scheduler zoom: Ctrl+wheel on the Scheduler zooms the board instead of the browser page.
- Sparkplug encoding: one Sparkplug tag that cannot be encoded is skipped and counted as untyped, instead of taking the whole node dark.
- TCP reconnects: a TCP client whose peer accepts and immediately hangs up is backed off, instead of being redialled thousands of times a second.
1.0.6
A licence you buy at 10am works at 10:01. Changed in 1.0.6 Every service
re-reads and re-verifies the signed licence file the moment one is installed, across the whole
fleet, within the same second. Before this, only two processes heard about it: a customer who added
the Siemens S7 and Allen-Bradley modules to a running installation watched the supervisor start
both workers — visible proof the purchase had landed — and then got MODULE_NOT_LICENSED when they
created a connection, because every other service was still holding the entitlements it read at
boot. The only cure was the restart the whole mechanism exists to avoid.
→ Licensing
Report by exception, for real. Changed in 1.0.6 Publish on change only has
been on by default since 1.0.0 and did nothing for the ordinary tag: the gate was the tag's
deadband, which defaults to 0 and is documented as a threshold for storage, so a tag with none
— which is most of them — went to the broker at the full scan rate, and a boolean was never
suppressed at all.
- A reading is now sent when it says something new: the value changed, or the quality did. Quality is part of the reading, not metadata about it — with Retain on, suppressing a Good→Bad transition at an unmoved value would leave the broker serving a Good-looking number to every late subscriber for as long as the process stood still.
- A heartbeat per publisher, off by default, re-sends the value already held after a chosen silence. RBE makes silence ambiguous — a process standing still and a dead gateway are both a topic that stopped — and a tag on a 250 ms poll with a 60-second heartbeat costs the broker one message a minute instead of 240.
- A tag can opt out on its own. Follow the broker / only when it changes / every reading, saved with the tag, because cadence is a property of the signal: a counter, a heartbeat or a batch step has to arrive at its scan rate wherever it is sent, and one tag can be in scope of several publishers at once.
The first run after upgrading drops existing publishers from scan rate to change rate. That is the intent and a large reduction — but it is a real change for a subscriber that was using message arrival as a liveness signal, which is what the heartbeat is for. → Report by exception
Publishing a folder is a checkbox, not a verb. Changed in 1.0.6 The tree's
Publishing menu now gives a folder and a multi-selection the same per-broker checkbox a tag
already had, with the third state that was blocking it: ticked, unticked, and a dash for a
folder the fence only reaches into. A dashed box hands off to the dialog rather than guessing —
"publish the rest" and "stop the ones that are" are equally plausible readings of the same click,
and that menu writes immediately. The dialog loses its Action radio, which was asking a second time
for a decision already made. And the bug underneath: stopping a folder now stops the subtree,
where before a publisher scoped to Line1/Pump and Line1/Valve made stopping Line1 report no
change and leave both tags publishing.
→ MQTT publishing
A backup that is honest about media. New in 1.0.6 The File Manager's content and the uploads store now travel — under a new Include File Manager & uploaded files flag that is off by default, because those folders hold videos and 3D models and a nightly backup dragging 400 MB of them is one that stops being run. The file list always travels either way, so a view that points at a document still points at it after a restore, and row and file reunite by content the moment the folders are copied across.
The honest part: on any instance built since August, the File Manager's content was in no archive at all. It had stopped being an internal catalogue and become an ordinary folder, and the backup went on carrying the catalogue — which was empty, and "0 files" is indistinguishable from an installation that never used the feature. Every guard stayed green. → Media
A backup moves between Linux, Windows and macOS. New in 1.0.6 Names that one filesystem stores and another cannot are now reported: refused on import for a project, view, script or query name, warned about on export while you can still rename the thing, and refused at creation for the names that are keys. The three silent cases are the reason — a trailing dot, a case variant and two Unicode spellings of one word each collapse two files into one with no error at either end. Passphrases are normalised before the key is derived, so an accented one typed on a Mac and on Windows opens the same archive. → Moving between operating systems
Writes to a PLC stop queueing behind other people's problems. Changed in 1.0.6
An audit of the Siemens S7 and EtherNet/IP write path, which had had less attention than the
read side. One dead panel used to stall writes to every other controller — and the caller was then
told worker unavailable about a worker that was perfectly healthy. An operator's setpoint now
goes in front of queued polling. A learned element size is discarded on reconnect, so a program
download cannot leave a stale width behind and reopen the silent partial write the probe exists to
close. A STRING write the CPU's PDU could only apply in halves is refused with the numbers and
the remedy rather than torn. And a value whose meaning is not obvious — 2 or maybe written to a
BOOL — is refused instead of quietly written as OFF.
→ Siemens S7 ·
Allen-Bradley
The script sandbox says what is actually installed. Changed in 1.0.6 The
allow-list pre-approves around thirty third-party libraries — numpy, pandas, cv2 — and ships
none of them installed. Allow-list membership is permission, not availability, and the two looked
identical on the screen; the first sign of the difference was a ModuleNotFoundError at run time.
Each entry now carries its own state, the list filters by it, and a missing one offers to install
itself.
→ The allow-list
A Problems panel, and one font size across every code editor. New in 1.0.6 The Designer hosts six separate Monaco editors and their size was fixed, so anyone who turned it up to read a long script had to do it again in the next panel. There was also nowhere to see what the linter had found — the footer showed a bare count, which tells you there is a problem and then declines to say what. Both linters already produced the message and the location; now you can click it. → The editor
The 3D Viewer's camera. New in 1.0.6 Motion is eased by default, in both directions: an
operator's rotate, pan and zoom glide to a stop instead of snapping, and a new pose — a target
re-aimed by an event action, a bound tag or an edit — flies there rather than cutting, so
nobody loses track of which way round the equipment is. enableRotate joins the gesture switches
so a fixed overview cannot be tumbled into a useless view. The [x, y, z] properties now name
their slots and fill the whole tuple in one click, where the grid used to show rows 0/1/2 and
its + appended a bare 0 — producing a 1- or 4-element array the widget rejected, so the field
appeared to do nothing.
→ 3D Viewer
AI: three more things a calculation can read. New in 1.0.6 Tag relationships, Manuals and Stored file join the input kinds for a specialist's compute body and a playbook's checks. A compute-only specialist runs no nested conversation and so holds no tools at all — its only data is that list — so until now a calculation over a commissioning record, a manual or a tag's stored links was not expressible, while a playbook could order the identical read in one step. A compute-only specialist is also now offered every kind: the dropdown followed the ticked skills, which that mode deliberately has none of, so Saved query never appeared and definitions the server accepts and runs could not be written in the editor. → Specialists
Also in the assistant: a compute body may be 40,000 bytes rather than 20,000 (a compute body is never sent to a model, so the old number was justified by a cost that does not exist); each turn is told which tools it actually holds, instead of inheriting a persona that describes every skill an installation might plug in; and Read files joins the other reads as a default, bounded by still needing Manage the library, which an operator cannot hold.
The AI node's defaults fit the work. Changed in 1.0.6 maxToolIterations
3 → 8 and the node timeout 15s → 60s. Three cannot finish the sequence the Database
Explorer skill documents — list the databases, introspect for tables, introspect for columns, then
query — so a node was cut off one call short and answered "I don't have access to any data
source", which reads as a permission problem and is not one.
→ AI node
A Python node's timeout reaches its system.* calls. Changed in 1.0.6 A node
given 600 seconds used to die on the first system.* call that ran past a fixed internal limit,
whatever the node was configured for.
Also in 1.0.6: a Windows arm64 build exists and is produced on request, deliberately out of the default release until somebody has run a gateway on one — an ARM64 laptop installs the x64 build today, and this manual's platform table had been listing arm64 as though it were a download.
Fixes worth knowing about: a tag bound over Siemens S7, Modbus, Allen-Bradley, SNMP or TCP/UDP
showed the raw connection UUID where its name belonged; a purged project left phantom
pipelines in the SuperAdmin statistics until a restart, and a project created after boot was
never watched at all; a failed request to the MQTT Publishing page rendered as "the MQTT Driver
module is not licensed" — the worst available mistranslation of "I could not reach the server",
because it sends somebody to look at their licence instead of at the error; unticking Retain, the
loop guard or publish on change only while creating a publisher was silently ignored; deleting
a specialist in the Pipeline workspace left its row in the tree; and a licensed service could
silently fail to hear about connection lookups, script file reads or the system.* worker API
because the bus had never been told to grant those subjects.
1.0.5
Siemens and Allen-Bradley controllers, spoken natively. New in 1.0.5 Two drivers, and deliberately two — a plant standardised on Siemens should not be carrying an Allen-Bradley licence.
- Siemens S7 reaches S7-300/400 and non-optimized S7-1200/1500
over classic S7comm, by absolute address: data blocks, flags, the process image, timers and
counters. The page carries a worked tag for every memory area, because the offset arithmetic
(
MW4is the word at byte 4, so the next one isMW6) is where the mistakes live. - Allen-Bradley (EtherNet/IP) reads Logix controllers by their own tag names. Browse pulls the symbol table and the UDT templates off the controller and fills in both the address and the data type, so you do not have to know either.
Both confirm an address before you bind it: a Read now button shows the decoded value and the raw bytes side by side, which is the difference between "this address is wrong" and "this type is wrong" — two problems that look identical in the number alone.
A refusal no longer costs you the connection. New in 1.0.5 Both drivers multiplex every tag onto a single link. A CPU refusing one address — a data block that does not exist, an offset past the end — is now reported against that tag alone. Every other tag on the controller keeps updating, and the link stays up.
Expression tags. New in 1.0.5 Derived values in CEL, compiled and cached, evaluated server-side. They are fail-closed: a missing input is an error on the tag, never a silent zero — which matters the moment somebody alarms on the result.
A backup you can actually restore from. New in 1.0.5 The archive now carries the whole schema and the File Manager's bytes, and a restore can run at first boot — before commissioning, rather than after it. See Backup & restore.
Licensing. New in 1.0.5 Per-module entitlement, enforced at the service boundary rather than in the UI.
A backup will not be read by a build that would read it wrongly. New in 1.0.5 Archives carry a compatibility floor measured from what they actually contain, so an estate that never touched a newer feature keeps producing archives older builds accept. Two silent-corruption bugs went with it: a restore no longer turns disabled connections, disabled tags and suspended users back on. → Backup & restore
1.0.4
Errors are something a pipeline can act on. New in 1.0.4 Until now a failed node was logged and its branch stopped. Two features change that, and they compose:
- The Catch node receives every failure in its pipeline — or a chosen few — and hands it to whatever should report it: a Telegram message, a dead-letter table, a Link into one central error-handling pipeline. The message it emits carries not only the error but the payload that caused it, so a failure can be replayed rather than only announced.
- A per-node error output puts a second, red socket on any node. Wire it and that node's failure carries on down a branch of its own, so a cached value can be substituted and the rest of the flow still runs. Off by default; every saved pipeline renders exactly as before.
A lost administrator password is recoverable, and a console reset cannot be quiet.
New in 1.0.4 qubiq admin reset-password at the server console prints a temporary password
once, forces a change at next sign-in, and ends every session that account held. It is recorded
three ways, one of which no one can dismiss. First-run setup is now genuinely one-shot: deleting the
user table no longer reopens the public setup endpoint, which is the hole this replaces.
→ Console recovery
The database encryption key has an escape hatch. New in 1.0.4 qubiq db-key create
prints a recovery key you write on paper. Without one, a changed service account or a rebuilt
profile could leave app.db permanently unreadable — which needs no attacker, just an ordinary
Tuesday. The key is also re-sealed on every boot so a service-account change stops being a data-loss
event. → Console recovery
A script may not do what its caller could not. New in 1.0.4 Tag write levels now apply to
system.tag.write, not just to a write from a screen; and a Gateway script started from a browser
button runs with the caller's own capabilities rather than unclamped. The Script Sandbox page also
says plainly, at the Install button, that a data library widens what scripts can reach — the sandbox
stops mistakes, not a determined author. → The script sandbox
Handled faults have their own log level. New in 1.0.4 WARN sits between routine chatter
and an outage, and is filterable. It also fixes a live bug: the log panel had been labelling every
warn row RETRYING, telling its reader to expect an attempt that was never coming.
Two new API reference pages — every system.* and context.* member, with worked examples in
both languages. → System API · Context API
An electrical symbol library. New in 1.0.4 529 electrical symbols across 24 categories — contacts, breakers, relays, logic gates, op-amps, MOSFETs, PLC ladder elements — join the 485 process symbols on the same canvas. 77 of them carry an operating state you can bind to a tag: a contact opens, a coil lights, a selector turns. Both states share a viewBox and terminal positions, so a bound line stays connected when the tag flips. → Drawing & symbols
The Breakpoint layout. New in 1.0.4 A fourth layout mode, for a screen whose phone version is a different screen rather than a narrower one. Each width tier gets its own authored panel and the view renders exactly one; a tier can mirror another, so a new view costs two screens rather than three. Switches at the project's own breakpoints, measures the container rather than the window (so they nest), and carries a dead-band for the flicker that happens when two tiers disagree about a scrollbar. → Breakpoint layout
The Timer node. New in 1.0.4 The pipeline runtime can now put time between messages — pulse a tag and put it back, hold a burst until it settles, delay every message, count down to a deadline, repeat on a cadence, or raise an alarm when a message that should have arrived did not. One independent timer per topic, controllable from the flow itself. → Timer node
Search that answers three questions. New in 1.0.4 A ⌘K / Ctrl+K palette across every
project; faceted tag filters in the namespace (is:disabled, no:binding, is:unused,
has:history, is:published, source:expression, …); where is this used for a tag or a
connection; and an impact warning before a rename or delete that names what will break.
→ Search & impact
Telegram sends a position. New in 1.0.4 A pin, a named venue, a live location this platform then moves as a vehicle moves, or a button asking a recipient to share theirs. → Telegram node
Numeric readouts keep their decimals. New in 1.0.4 The Gauge, Tank, Moving Analog
Indicator and HMI Trend take a decimals property instead of rounding a value away. A tag reading
23.998 is no longer displayed as 24 with no way to get the fraction back.
→ Gauge
Zoom and fit controls on the pipeline canvas. New in 1.0.4 Undo, redo, zoom in and out, reset to 100% and zoom-to-fit, with their keyboard equivalents shown on each.
The Connected column carries a date. New in 1.0.4 A LiveView screen on a wall stays up for
days, and a bare 14:03 on such a row reads as a few minutes ago when it was Tuesday. The full
instant is in the cell's tooltip.
Also in 1.0.4: the trial is recorded outside the data directory, so deleting that folder no longer
buys a second one; and the pipeline-level POST /api/pipelines/{id}/execute route was removed — it
answered 500 on every call it ever received, and nothing used it.
Fixes worth knowing about: node status badges never rendered in a production build; the runtime's
STALE indicator was measuring clock skew rather than staleness; Python results were being refused
by the bus, and child processes looked for the interpreter in the wrong directory.
1.0.3
A configuration fix that matters on every production install: every service opened a different
app.db. Also: the import browser no longer collapses, and the storage folder picker no longer
flickers or turns unreadable on hover.
1.0.2
AI Specialists can compute. New in 1.0.2 A specialist may carry a Python compute body, run end to end behind every fence, and declare its inputs once — so a figure is calculated exactly rather than worked out in a model's head. A specialist can also be saved as a draft: testable by its author, withheld from the assistant. → Answering with code
The trial is 21 days, not 7. New in 1.0.2 A week can vanish waiting for PLC access or a downtime window. → Licensing
On Windows, double-clicking the executable no longer flashes a console, and an uninstalled copy refuses to run.
1.0.1
P&ID line types. New in 1.0.1 ISA-5.1 tells signal lines apart by a repeated glyph rather than by colour — pneumatic hashes, data-link circles, a capillary X, a sonic wave. A line now carries its meaning as a property. → Drawing & symbols
Fittings that ride the pipe. New in 1.0.1 A flange, orifice plate, strainer or spectacle blind sits on a run at a normalised position along it, and stays there through a drag, a bend or a change of routing mode. → Drawing & symbols
A multi-value Progress bar. New in 1.0.1 One track, several coloured segments, each separately bindable, in absolute or proportional mode. → Progress
Storage folders are browsed, not typed. New in 1.0.1 A server-side folder picker with OS-aware suggestions, so a path is chosen rather than guessed at.
The status panel shows every volume QUBIQ writes to, not just one. New in 1.0.1
Open-source notices. New in 1.0.1 A third-party licence inventory, and the page that
shows it, at /notices.
Also in 1.0.1: multi-touch pinch and pan on the Designer and pipeline canvases; a rebuilt Windows installer, and the same application identity on macOS and Linux; and licence status in the app status bar.
The Breakpoint Container widget was withdrawn from the component library in this release. The idea returned in 1.0.4 as a layout mode rather than a widget you drag from the palette — its containers are structural, so they are not in the component reference.
1.0.0
The first release. The parts of it this manual gained pages for:
MQTT publishing. New in 1.0.0 Mirror namespace tags out to an external broker — classic MQTT or Sparkplug B, with scope and exclusion fences, four layers of loop protection, and a choice between live and durably-buffered delivery. → MQTT publishing
Per-module licensing. New in 1.0.0 Offline, hardware-bound activation; a modules page that never hides what you do not own; and a lapse that degrades visibly rather than stopping a plant. → Licensing & modules
The Switch node. New in 1.0.0 The first router in the pipeline runtime, and the only node with more than one output. → Switch node
A Color Picker widget, and menu components that can run an action instead of navigating. → Color Picker · Horizontal Menu
AI playbooks, specialists and named endpoints. New in 1.0.0 An answer procedure written down once so every phrasing of a question gets the same complete answer; saved sub-assistants the assistant hands one sub-question to; and an admin-authored menu of lookups into an ERP or a CMMS that the model can select from but never compose. → Playbooks · Specialists · External systems · Skills & fences
The platform at a glance
What QUBIQ does, and where each part is documented.
Platform
Ships as one file. A single executable contains every service. Starting it with no arguments
boots the supervisor, which runs one process per service under its own QBQ-* name.
→ Architecture
Zero-port internal bus. The message bus binds to loopback on a random port. No broker port is exposed, authenticated or firewalled, and no service other than the gateways opens a port. → The gateway
Encryption at rest. The configuration database is encrypted with a key bound to the machine it
runs on. JWT_SECRET and ENCRYPTION_KEY are required, with no insecure defaults.
→ Security
In-app setup wizard. There is no default account and no create-superadmin step; the first super admin is created through the interface, once. → First-run setup
Connectivity
Protocol coverage — OPC-UA, MQTT with Sparkplug B, Modbus, SNMP (v1/v2c/v3 with vendor MIBs and traps), raw TCP/UDP, SQL, MongoDB, QuestDB and media servers — plus SMTP, Telegram and WhatsApp for notification and a Qdrant vector store for the assistant. → Connections
Publishing out, not just reading in: tags mirrored to an external broker in classic MQTT or Sparkplug B, at the change rate rather than the scan rate, with a per-publisher heartbeat and a per-tag cadence. → MQTT publishing
Passive liveness. Connection health comes from the protocol libraries' own callbacks rather than
from polling. LIVENESS_MODE selects passive (default), hybrid or active.
→ Connections
OPC-UA node quarantine. A repeatedly-failing node is quarantined so one bad address cannot degrade a whole subscription, with a release path when the PLC program is fixed. → OPC-UA
Isolated MIB compilation. Vendor SNMP MIBs are compiled in a separate child process, so a malformed MIB cannot crash the gateway. → SNMP
Data model
User-defined types with parameters, nesting, reconciliation planning, per-instance overrides and member-context capture/revert. → User-defined types
Portable namespace import/export. Documents carry no database identifiers and reference connections by name, so a model moves between environments cleanly. → Bulk import & export
Tag write-security levels. A 0–3 hierarchy enforced server-side, independent of the writable flag. → Tags
Reference tracking. Where a tag is used, what a rename would break, and what nothing references at all. → Search & impact
Historian
History epochs. Changing the historian is non-destructive: reads resolve across epochs and stitch the timeline. Range statistics are recombined exactly rather than averaged. → Historian
Physical store ownership. Ownership is recorded inside the QuestDB store, so a cloned VM or a restored backup cannot silently corrupt a live historian. → QuestDB
Self-healing. Schema-drift detection with rebuild, write-ahead-log supervision that distinguishes recoverable stalls from poison segments, and on-demand rollup rebuild. → Historian configuration
Live-tail merge. Recent in-memory samples are merged into live chart queries, so charts look live despite batched storage.
Reliability
Store and forward for all outgoing data writes: a durable per-connection buffer, ordered ack-after-flush drain, an ordering latch, transient-versus-permanent failure classification, buffer pressure alarms and an operator quarantine. → Store and forward
Pipeline error handling — a Catch node that reports any node's failure with the payload that caused it, and a per-node error output that lets the flow recover in place. → Errors
Alarms
ISA-18.2 lifecycle — NORM / UNACK / ACK / RTNUN, with latching, require-ack, on/off
delays, absolute and percentage deadbands, and bad-quality alarming.
→ Configuring alarms
Three distinct suppression kinds — timed shelving with automatic release, indefinite suppress-by-design, and out-of-service — so the reason an alarm is silent is always recorded. → Operating alarms
Performance metrics — rate, floods, bad actors, priority distribution and standing alarms.
Visualization
53 widgets, 9 drawing tools, 1048 symbols — 485 process (P&ID) and 529 electrical, plus 3D model viewing, PDF, video, maps, scheduling and a full form engine. → Components
Vector drawing with orthogonal, isometric and curved routing, endpoint binding to equipment, ISA-5.1 line types, in-line fittings and stroke animation for process mimics. → Drawing & symbols
Four layout modes — coordinate, grid, flex and breakpoint — chosen per view. Breakpoint gives each width tier its own authored screen rather than reflowing one. → Views and layout · Breakpoint layout
Optimistic locking on views, scripts and pipelines: a conflicting concurrent save is rejected rather than silently overwriting.
Streamed query results in LiveView, so a large result set renders as it arrives rather than after it has all landed.
Pipelines
23 node types across eight categories — sources, routing, protocol I/O, databases, transforms, AI, notification, REST and error handling. → Node reference
Scripting
One API surface in two languages. system.* is identical, camelCase, in Python and JavaScript.
→ System API reference
Gateway scripts with default-deny @gateway exports, static AST-based discovery, per-entry-point
timeouts and idempotency keys. → Gateway scripts
Managed transactions with isolation levels and a server-side TTL, so a browser disconnect cannot strand an open transaction.
Capability scopes gating every system call, fail-safe by default — a newly-added API is gated
rather than accidentally open. → The script sandbox
Administrator-installed Python packages, isolated in a managed directory with a connectivity check for air-gapped networks.
Security
Two independent sign-in systems. Engineers and plant operators sign in separately, against different user stores. Neither system accepts the other's sign-in. → LiveView authentication
Tamper-evident audit journal in an external SQL database, hash-chained, durable-buffered, with a verification endpoint — aligned to IEC 62443-3-3. → Audit journal
Scoped API keys, hashed at rest, with fail-closed REST routes, IP allow-lists, rate limits and payload caps. → API keys
Sandboxed user SQLite connections, confined to a resolved directory with traversal and internal-database denial.
Console recovery without a back door. A lost administrator password and a lost database key are both recoverable by somebody with the server's data directory, and by nobody else. Every reset is audited and surfaced where an administrator will see it. → Console recovery
AI assistant
Propose-and-approve. The assistant drafts views, pipelines, alarms and queries as proposals a human approves. Actions are audited under both the assistant and the approving user. → AI assistant
Skills, realms and fences. What an assistant may do is the intersection of its skills, where it runs, what the administrator switched on, and what the person asking already holds — and each instance carries its own fences over tags, databases, external systems and specialists. → Skills & fences
Playbooks and specialists — a procedure written down once, and saved sub-assistants with their own fences and budgets. → Playbooks · Specialists
Per-connection access and read-only credentials, so the assistant can explore a production database without being able to change it.
Administration
Per-module, offline licensing with a modules page that locks rather than hides, and a licence that reaches every running service without a restart. → Licensing & modules
Backup and restore with whole-archive passphrase encryption, secret re-keying between machines, opt-in media, and a filename pre-flight that makes an archive portable between Linux, Windows and macOS. → Backup & restore
Project lifecycle — enable, disable, trash with a 30-day retention window, restore and purge. → Projects
Service control from the interface, with the supervisor honouring a deliberate stop. → Services
Upgrading
- Take a backup — schema migrations are not reversible.
- Stop the service.
- Replace the binary.
- Start it. The supervisor migrates the schema before spawning children.
- Check the startup report, then verify connections and pipelines.
Coming from 1.0.5, two changes are worth checking after the first start:
- MQTT publishers drop to the change rate. Intended, and a large reduction — but if a subscriber was treating message arrival as a liveness signal, give the publisher a heartbeat.
- Exports no longer carry File Manager or uploaded files by default, so the next backup will be dramatically smaller than the last. Tick Include File Manager & uploaded files for a full disaster-recovery copy, or back those two folders up with your file-backup tool. → Media
Keep .env. Losing ENCRYPTION_KEY makes every stored credential unrecoverable, and losing this
machine's database key store makes app.db unreadable — so run qubiq db-key create and file the
code somewhere off the machine. → Console recovery
A licence names the versions it covers. Upgrading past that ceiling reports version not covered — not unlicensed — and the remedy is to install the version you own or extend the licence. → Licensing