IoT — worked graph designs

These designs describe intended system behavior and qualification requirements. Inspect the system atlas for named ports and relation participants.

IoT: constrained sensors, gateway buffering and ingestion

What can a gateway acknowledge during a cloud outage?

Inspect this design · Definition JSON · revision 120a91db6121

Diagram legend. Frames are named graph regions. Left/right pins show required/offered participation, not a universal schedule. Filled pins are connected; hollow pins are unbound. A junction card preserves one relation's role slots.

MarkerMeaning in this diagram
⊟ N30External system boundary
▣ N05Actor / statechart
≋ N24Queue / log / pubsub resource
↗ N19Tool / external API adapter
▰ N21Database / state authority
⌕ N22Query / materialized view
↦ P04Push event
◎ P24Inspection / evidence
⇆ P02Request / response
→ H02Value flow
⇆ H05Request / reply binding
↦ H04Event subscription
⊢ H27Derivation / provenance

Logic and ownership

Kotlin common logic validates units and groups samples at the gateway; constrained firmware remains an explicit external system boundary when Kotlin/JS cannot execute there.

Failure and qualification

  • Gateway durability and cloud commit have distinct acknowledgements.
  • Retention limits and outage overflow behavior must be specified.
  • Device identity, sample sequence and clock uncertainty travel with the batch.

Hyperedge roles

RelationPatternParticipants, preserving role positions
sampleH02 — Value flow {#h02--value-flow}provider[0]: sensor.sample; consumer[0]: gateway.sample
bufferH05 — Request / reply binding {#h05--request--reply-binding}provider[0]: buffer.append; consumer[0]: gateway.buffer
uploadH05 — Request / reply binding {#h05--request--reply-binding}provider[0]: ingest.batch; consumer[0]: gateway.upload
storeH05 — Request / reply binding {#h05--request--reply-binding}provider[0]: series.append; consumer[0]: ingest.storage
healthH04 — Event subscription {#h04--event-subscription}provider[0]: gateway.health; consumer[0]: health.events
lineageH27 — Derivation / provenance {#h27--derivation--provenance}device[0]: sensor.identity; gateway[1]: buffer.position; cloud[2]: series.receipt

Kotlin common declaration

Import dev.shibasis.reaktor.portgraph.definition.* for this structural declaration. Behavior stays in ordinary Kotlin and binds through qualified runtime ports and adapters. Declaring a graph does not activate a system.

graphDefinition("iot-sensor", "120a91db6121e8d92f1d0a4ceef8b562284679ecebac1ab725f1648b5f995a35") {
    region("device", "Constrained devices")
    region("gateway", "Gateway")
    region("cloud", "Cloud authority")
    node("sensor", "Sensor firmware boundary", "N30", "device", ports = listOf(
        PortDefinition("sample", "P04", "SensorSampleV1", PortPolarity.Offer),
        PortDefinition("identity", "P24", "DeviceRefV1", PortPolarity.Neutral)
    ))
    node("gateway", "Gateway actor", "N05", "gateway", ports = listOf(
        PortDefinition("sample", "P04", "SensorSampleV1", PortPolarity.Require),
        PortDefinition("buffer", "P02", "GatewayAppendV1", PortPolarity.Require),
        PortDefinition("upload", "P02", "SensorBatchV1", PortPolarity.Require),
        PortDefinition("health", "P24", "DeviceHealthV1", PortPolarity.Offer)
    ))
    node("buffer", "Gateway durable buffer", "N24", "gateway", ports = listOf(
        PortDefinition("append", "P02", "GatewayAppendV1", PortPolarity.Offer),
        PortDefinition("position", "P24", "LogPositionV1", PortPolarity.Neutral)
    ))
    node("ingest", "Cloud ingestion", "N19", "cloud", ports = listOf(
        PortDefinition("batch", "P02", "SensorBatchV1", PortPolarity.Offer),
        PortDefinition("storage", "P02", "SeriesAppendV1", PortPolarity.Require)
    ))
    node("series", "Time-series authority", "N21", "cloud", ports = listOf(
        PortDefinition("append", "P02", "SeriesAppendV1", PortPolarity.Offer),
        PortDefinition("receipt", "P24", "ReceiptRefV1", PortPolarity.Neutral)
    ))
    node("health", "Fleet health view", "N22", "cloud", ports = listOf(
        PortDefinition("events", "P24", "DeviceHealthV1", PortPolarity.Require)
    ))
    relation("sample", "H02",
        Incidence("sensor", "sample", "provider", 0),
        Incidence("gateway", "sample", "consumer", 0)
    )
    relation("buffer", "H05",
        Incidence("buffer", "append", "provider", 0),
        Incidence("gateway", "buffer", "consumer", 0)
    )
    relation("upload", "H05",
        Incidence("ingest", "batch", "provider", 0),
        Incidence("gateway", "upload", "consumer", 0)
    )
    relation("store", "H05",
        Incidence("series", "append", "provider", 0),
        Incidence("ingest", "storage", "consumer", 0)
    )
    relation("health", "H04",
        Incidence("gateway", "health", "provider", 0),
        Incidence("health", "events", "consumer", 0)
    )
    relation("lineage", "H27",
        Incidence("sensor", "identity", "device", 0),
        Incidence("buffer", "position", "gateway", 1),
        Incidence("series", "receipt", "cloud", 2)
    )
}

IoT: commissioning, scoped commands and signed firmware

Which authority permits a physical command or firmware update?

Inspect this design · Definition JSON · revision 1a11b20d7611

Diagram legend. Frames are named graph regions. Left/right pins show required/offered participation, not a universal schedule. Filled pins are connected; hollow pins are unbound. A junction card preserves one relation's role slots.

MarkerMeaning in this diagram
✓ N20Human decision / approval
⊂ N33Policy / principal boundary
↗ N19Tool / external API adapter
▸ N27Runtime host / executor
⊟ N30External system boundary
▧ N35Artifact / release manifest
▣ P03Durable command / receipt
◎ P24Inspection / evidence
⊂ P20Authorization request / grant
⇆ P02Request / response
▧ P23Artifact / schema reference
→ H02Value flow
⊂ H23Scoped authorization
⇆ H05Request / reply binding
▧ H26Artifact dependency

Logic and ownership

Kotlin evaluates commissioning identity and command scope at the gateway. Firmware admission remains in the target bootloader or update authority.

Failure and qualification

  • A signed artifact authenticates its publisher, not the safety of every physical action.
  • The device can reject an expired or unsafe command after cloud admission.
  • Firmware and subgraph code push use different executable formats and recovery constraints; neither implies a universal Kotlin/JS device runtime.

Hyperedge roles

RelationPatternParticipants, preserving role positions
proposalH02 — Value flow {#h02--value-flow}provider[0]: operator.intent; consumer[0]: command.intent
grantH23 — Scoped authorization {#h23--scoped-authorization}provider[0]: policy.grant; consumer[0]: command.authority
deliverH05 — Request / reply binding {#h05--request--reply-binding}provider[0]: gateway.execute; consumer[0]: command.deliver
deviceH05 — Request / reply binding {#h05--request--reply-binding}provider[0]: device.command; consumer[0]: gateway.device
artifactH26 — Artifact dependency {#h26--artifact-dependency}provider[0]: bundle.artifact; consumer[0]: gateway.artifact
admissionH23 — Scoped authorization {#h23--scoped-authorization}principal[0]: operator.principal; resource[1]: device.identity; policy[2]: policy.policy; executor[3]: gateway.executor

Kotlin common declaration

Import dev.shibasis.reaktor.portgraph.definition.* for this structural declaration. Behavior stays in ordinary Kotlin and binds through qualified runtime ports and adapters. Declaring a graph does not activate a system.

graphDefinition("iot-command", "1a11b20d761148f7f75f75d0d955905cec811445932dd24149e5dc54500c9757") {
    region("device", "Constrained devices")
    region("gateway", "Gateway")
    region("cloud", "Cloud authority")
    node("operator", "Operator proposal", "N20", "cloud", ports = listOf(
        PortDefinition("intent", "P03", "DeviceIntentV1", PortPolarity.Offer),
        PortDefinition("principal", "P24", "PrincipalRefV1", PortPolarity.Neutral)
    ))
    node("policy", "Device policy", "N33", "cloud", ports = listOf(
        PortDefinition("grant", "P20", "DeviceGrantV1", PortPolarity.Offer),
        PortDefinition("policy", "P24", "PolicyRefV1", PortPolarity.Neutral)
    ))
    node("command", "Command service", "N19", "cloud", ports = listOf(
        PortDefinition("intent", "P03", "DeviceIntentV1", PortPolarity.Require),
        PortDefinition("authority", "P20", "DeviceGrantV1", PortPolarity.Require),
        PortDefinition("deliver", "P02", "DeviceCommandV1", PortPolarity.Require)
    ))
    node("gateway", "Gateway executor", "N27", "gateway", ports = listOf(
        PortDefinition("execute", "P02", "DeviceCommandV1", PortPolarity.Offer),
        PortDefinition("device", "P02", "DeviceProtocolV1", PortPolarity.Require),
        PortDefinition("artifact", "P23", "FirmwareRefV1", PortPolarity.Require),
        PortDefinition("executor", "P24", "HostRefV1", PortPolarity.Neutral)
    ))
    node("device", "Device controller boundary", "N30", "device", ports = listOf(
        PortDefinition("command", "P02", "DeviceProtocolV1", PortPolarity.Offer),
        PortDefinition("identity", "P24", "DeviceRefV1", PortPolarity.Neutral)
    ))
    node("bundle", "Signed firmware artifact", "N35", "cloud", ports = listOf(
        PortDefinition("artifact", "P23", "FirmwareRefV1", PortPolarity.Offer)
    ))
    relation("proposal", "H02",
        Incidence("operator", "intent", "provider", 0),
        Incidence("command", "intent", "consumer", 0)
    )
    relation("grant", "H23",
        Incidence("policy", "grant", "provider", 0),
        Incidence("command", "authority", "consumer", 0)
    )
    relation("deliver", "H05",
        Incidence("gateway", "execute", "provider", 0),
        Incidence("command", "deliver", "consumer", 0)
    )
    relation("device", "H05",
        Incidence("device", "command", "provider", 0),
        Incidence("gateway", "device", "consumer", 0)
    )
    relation("artifact", "H26",
        Incidence("bundle", "artifact", "provider", 0),
        Incidence("gateway", "artifact", "consumer", 0)
    )
    relation("admission", "H23",
        Incidence("operator", "principal", "principal", 0),
        Incidence("device", "identity", "resource", 1),
        Incidence("policy", "policy", "policy", 2),
        Incidence("gateway", "executor", "executor", 3)
    )
}