Priostack · Engineering Blog · 21 August 2026 · 10 min read

One Engine, Three Surfaces

Deep diveConceptEngineering

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.

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.

The property in one line. The same model means the same thing on every surface, because the same engine runs it on every surface. Consistency is not maintained by discipline across teams; it is a fact about the runtime.

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:

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:

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.

Why this beats a shared service. A shared decision service still leaves view logic reimplemented per platform and still fails offline. Here the view and the process run on the same engine everywhere, so the offline screen and the canonical fact use one runtime - not a client calling a server that reimplements the rule.

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.

What this does and does not buy you. Making an unsafe state unreachable in the model is strong. It does not make the hardware infallible - a sensor can lie, a board can fail, a radio can drop. Skopin reduces the class of bugs where the logic permits something it never should; it does not repeal physics. Field devices still need the ordinary discipline of failure handling.

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.

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.

Related reading - For how execution position becomes recall, see Geometric memory. For where canonical durable state actually lives, see QDB. For the models as legible structure, see ArchiMate layers.

Priostack Engineering

Technical deep-dives on process automation, workflow engines, and the systems behind Priostack.