The model
Three layers, four pillars, and the rule that decides who may call whom.
Klorad follows the system model of the doctoral thesis Spatial Computing and Geospatial Science for Virtual Worlds and Digital Twins (University of Macedonia). The model has three layers, which say where code lives, and four pillars, which say what a twin must get right.
Three layers
@klorad/accessHow people and devices reach the world: Worlds, entitlement, audit.@klorad/api/integrationHow the world is coupled to reality: sources, devices, connectors.@klorad/api/worldOwns meaning. Pure TypeScript: no React, no renderer, no database.SpaceTimePhysical correspondenceInteraction and actuation@klorad/engine-threeDraw what World defines.@klorad/reactDeclare objects, read state with hooks.World owns meaning: the scene, the objects in it, how each corresponds to the physical world, the readings that describe it, and the rules that change it. It is pure TypeScript. It does not import React, a renderer, a database or the network, so the same world runs in a browser, on a server and in a test.
Access is how people and devices reach the world: who may enter which view of it, and who
may take which Action. It lives in @klorad/access.
Integration couples the world to reality: sensors, vendor APIs, devices that accept
commands. It lives in @klorad/api/integration.
Access and Integration depend on World. World never depends on them: when it needs an answer
only Access can give (may this person do this?), it defines a small interface and Access
implements it. That is why createInteraction asks for an entitlement instead of importing
one.
Renderers and React bindings sit outside the layers. They read the world and draw it; they never change it. An app that wants to change world state calls the scene.
Four pillars
| Pillar | What it guarantees | Page |
|---|---|---|
| Space | Every scene has an Earth anchored coordinate system, so every position is a real place. | Space |
| Time | Readings are ordered by when they were observed. A late reading never overwrites a newer state. | Time |
| Physical correspondence | Every object declares whether it is modelled only, mirrored one way, or mirrored both ways. | Physical correspondence |
| Interaction and actuation | An Action is checked by an Entitlement, then a Behaviour changes state and an Animation shows it. Never backwards. | Interaction |
The code was built in that order, because each pillar needs the one before it: there is no meaningful time without a place, no correspondence without time, and no safe actuation without correspondence.
From thesis class to export
| Thesis class | Export | Package |
|---|---|---|
| 3D Scene | createScene, Scene | @klorad/api/world |
| Coordinate System | createCoordinateSystem, CoordinateSystem | @klorad/api/world |
| Scene Object | SceneObject, SceneObjectSpec | @klorad/api/world |
| Digital Object, Shadow, Twin | DigitalObject, DigitalShadow, DigitalTwin | @klorad/api/world |
| Time Spectrum | Clock, Observation, compareObservations | @klorad/api/world |
| IoT Devices, APIs | ObservationSource, connectSource, fixtureSource, pollingSource | @klorad/api/integration |
| Action, Behaviour, Animation | ActionDefinition, BehaviourDefinition, AnimationRequest, createInteraction | @klorad/api/world |
| Entitlement System | Entitlement (asked by World), createAccessPolicy (answers) | @klorad/api/world, @klorad/access |
| Actuation of a Twin | Actuator, Command, fixtureDevice | @klorad/api/world, @klorad/api/integration |
| Worlds (entitled views) | World, inScope, projectScene, audit log | @klorad/access, @klorad/api/world |
| Rendering | createThreeRenderer, ThreeView | @klorad/engine-three |
A new export needs a class in this table or a recorded architecture decision behind it. That rule keeps the API small and keeps it meaning one thing.
Something wrong or unclear? Tell your contact at Prieston Technologies.