One Engine, Three Surfaces
Most platforms that reach a phone, a browser, and a device in the field end up building the same product three times. There is a native app team, a web team, and whoever owns firmware. Each one re-derives what a workflow means, what a decision returns, when a case is closed. They agree on paper and drift in practice, because the same rule now lives in three languages maintained by three groups on three release cadences.
Priostack refuses that shape. There is one engine - Qubit - and it runs the same models on every surface. A phone, a browser tab, and a Skopin edge node are not three implementations of the product; they are three renderers in front of one runtime. This piece is about why that matters, what it costs, and one decision it forces you to make honestly: which state lives on the device and which state is canonical on the engine. That split is not a preference. It falls out of what each model actually describes.
None of this makes the hard problems disappear. Offline devices still diverge, edge hardware still fails, and geometric recall still has a ceiling we will name out loud. But it removes one whole category of bug - the "it behaves differently over there" bug - by construction.
Contents
1. The cost of reimplementing three times
Consider a single rule: an order over a certain amount needs a second approval before it ships. On the native app it is written one way. In the web client, someone re-writes it in the language of the browser. On the device that actually gates the shipment, it becomes a firmware check. Three copies of one sentence.
The failure is not that any one copy is wrong. It is that they are copies at all. When the threshold changes, three teams have to change it, ship it, and line up their releases. Between those releases the surfaces disagree, and a disagreement about "does this need approval" is exactly the kind of gap that becomes an incident. The bug is structural: three sources of truth for one truth.
The usual mitigation is a shared service that all three call. That helps for decisions you can round-trip to a server. It does nothing for a device in a field with no signal, and it does nothing for view logic, which by nature runs where the person is looking. So you are back to reimplementing the parts that have to be local, and back to drift.
2. One engine underneath
Qubit is the single engine that sits under the consumer app, under the developer API, and out at the edge. It runs BPMN 2.0 processes, DMN 1.3 decisions, and CMMN 1.1 cases natively - not as documentation that a programmer then translates into code, but as the thing that actually executes. A BPMN process is run as a Petri net. A DMN table is evaluated as a decision. A CMMN case is tracked as a case.
Because the engine is the same everywhere, the model is the interpreter. There is no second translation step where meaning can leak. The order-approval rule is defined once, as a model, and every surface that needs it asks the same engine the same question and gets the same answer.
3. An app is a bundle of models, not code
A third-party Priostack app is not a binary you install. It is a bundle of models, each covering one facet of the app, in standard notations:
- ArchiMate 4.0 - the structure: what parts exist, how they relate, which technology nodes they run on.
- BPMN 2.0 - what the app does, the processes, run as Petri nets.
- CMMN 1.1 - the cases, the work that is not a straight line but a set of things that may happen.
- DMN 1.3 - the decisions, the tables and rules that turn inputs into outcomes.
- Camel YAML - the integrations and routes out to other systems, expressed as Enterprise Integration Patterns.
- IFML - the views, the interaction the person actually touches.
This is what makes one engine on three surfaces possible in the first place. There is no platform-specific code to port, because the app was never code. It is a description the engine already knows how to run. Shipping to a new surface is not a rewrite; it is pointing that surface's renderer at the same models.
It also means the models are legible. An ArchiMate diagram of the app is not a sketch drawn after the fact and left to rot - it is part of what runs. A technology-layer node in that diagram can be a real device in the field. The picture and the system do not drift apart, because the picture is the system.
4. Three surfaces, one meaning
The three surfaces differ only in how they draw and where they run, not in what they mean:
+---------------------------------------------+
| QUBIT engine |
| BPMN (Petri nets) · DMN · CMMN · models |
+----------------------+----------------------+
|
same models, same meaning |
+---------------------+---------------------+
| | |
+---------------+ +---------------+ +----------------+
| Native app | | Browser | | Skopin edge |
| Android/iOS | | PWA | | node (field) |
| draws IFML | | JS renderer | | runs policies |
+---------------+ +---------------+ +----------------+
phone in hand a tab open a board on a wall
On a phone, the native renderer draws the IFML views. In a browser, a JavaScript renderer draws the same views as a PWA. On an edge device, Skopin runs the app's models and policies where the work physically happens. Three ways of presenting and executing, one definition of what is true.
The interactive part - what a view is showing right now, the half-filled form, the toggle you just flipped - is local to the device and works offline. The durable part - the state of a process, the outcome of a decision, whether a case is open or closed - is canonical on the engine. Which brings us to the one split you cannot hand-wave.
5. The device/engine split, decided by the model
The tempting question is "should this state live on the device or on the server?" - answered by taste, by whichever is easier this week. That is the wrong question, and answering it by preference is how you get inconsistency back in through the side door.
The split is decided by what the model describes:
- Interactive view state is local. An IFML view is about the here-and-now of one screen on one device. Its state belongs to that device, and it must keep working with no network, because a person tapping a screen should not wait on a round trip. This state is ephemeral by nature.
- Durable process, decision, and case state is canonical on the engine. A BPMN process, a DMN outcome, a CMMN case is a fact about the world that other people and other surfaces depend on. It cannot have two versions. It lives on the engine and is the single source of truth, whatever surface last touched it.
So a form you are filling in is yours, on your device, offline. The moment you commit an approval, that is a process fact, and it belongs to the engine where every surface will read the same answer. The boundary is not a judgement call per feature - it is a consequence of which model the state came from. View models stay local; process, decision, and case models are canonical. That is what keeps three surfaces honest instead of merely coordinated.
6. Skopin at the edge: safety by construction
Skopin is Priostack's Linux edge OS. It runs an app's models and policies on a device in the field, receives its deployments from Priostack over its own protocol, and reports the device's real state back. A technology-layer node in an ArchiMate model is not a label for a device - it can be the device, running Skopin.
On a control device, Skopin runs a fast, repeating scan cycle - on the order of 120 ms. Sensor readings become read-only guards in the model. And because BPMN runs as Petri nets, an unsafe combination of states can be made structurally unreachable rather than merely checked. If two interlocked states must never both hold, you do not write a runtime "if" that someone can forget - you build the net so that marking cannot exist. Safety by construction is a property of the Petri-net semantics, not a convention the programmer is trusted to honour.
Reflex is the reference hardware for this: a small Linux board with Wi-Fi, 4G, an eSIM, a microSD, IEEE 802.15.4, and expansion for Z-Wave, XBee, and LoRa. The family framing is simple - Priostack orchestrates, Skopin executes at the edge, Reflex anchors it in the physical world. The same models that drew a screen on a phone can gate a physical interlock on a board, because the same engine runs both.
7. When a model is not enough: native features
Models cover a lot, but not everything. A camera, a cryptographic key, placing a phone call - these are not things BPMN or DMN can express. For those, the surrounding app provides a permissioned native feature. It is granted with a stated purpose and an expiry, and it is enforced when it is invoked, not blanket-approved at install time.
This keeps the honesty of the model-driven approach intact. The models say what the app does; the native features are the few explicit, time-boxed exceptions where the app reaches past what a model can describe. Nothing important hides in "code" you cannot inspect, because the parts that would have been code are models, and the parts that cannot be models are named, scoped, and expiring grants.
This sits inside the wider autonomy model - Suggest, Prepare, Confirm, Delegated, Continuous - where the effective autonomy is always the lower of what an app asks for and what a person grants, and where money and account-security actions are capped at Confirm no matter what the app declares. A native feature is granted the same honest way: you see the side effect before you allow it.
8. Honest limits
One engine on three surfaces is a real simplification, not a slogan, but it has edges worth naming.
- Offline still means divergence. Local view state working offline is a feature, but a device out of contact has a stale picture of canonical state until it reconnects. The split makes the reconciliation well-defined; it does not make the gap zero.
- The edge is still the physical world. Safety by construction constrains the logic, not the hardware. Sensors drift, boards die, links drop. Skopin reports real state back precisely because the real state is not guaranteed.
- Geometric memory matches projections, not paraphrase. The context store recalls by similarity of execution position rather than by key, which is powerful for finding "paths like this one." Today it matches deterministic projections of values, not semantic paraphrase - two runs that mean the same thing in English but took different shapes are not yet close by that measure. It is a genuine capability with a genuine ceiling.
- One engine is one thing to get right. The flip side of no drift is that the engine's semantics are load-bearing everywhere at once. A single runtime concentrates both the benefit and the responsibility.
Conclusion
The reason to run one engine on three surfaces is not elegance for its own sake. It is that meaning should not be a thing you maintain in triplicate. When an app is a bundle of models and the same engine runs those models on a phone, in a browser, and on a Skopin node, the order-approval rule is one sentence, defined once, meaning the same thing wherever it is read. The device/engine split is not a preference to argue about per feature - view state is local because IFML describes the here-and-now, and process, decision, and case state is canonical because those models describe facts the whole system shares.
You still owe the field the ordinary honesty about offline gaps, hardware failure, and where recall stops. But you no longer owe anyone the answer to "why does it behave differently over there," because there is no over there. There is one engine, three surfaces, and one meaning.