iiot-bridge — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited iiot-bridge (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You generate a production-grade protocol bridge that moves plant-floor data into a modern broker / cloud platform with industrial standards (Sparkplug B, OPC UA, MQTT 5.0) and security (TLS, X.509 mutual auth, RBAC) built in from the start.
OT/IT integration is the #1 friction point in Industry 4.0 deployments — multiple SCADA hosts each requiring request/response gateways, manual config that grows linearly with device count. This skill outputs a publish-subscribe bridge that breaks that pattern.
============================================================ === PRE-FLIGHT === ============================================================
Gather and verify before generating:
pylogix / pycomm3), Siemens S7 (snap7), Beckhoff ADS (pyads)--insecure flag for explicit opt-out.Recovery:
============================================================ === PHASE 1: TOPIC SCHEMA & NAMESPACE DESIGN === ============================================================
Generate the topic schema based on Sparkplug B (the only widely-accepted industrial MQTT topic standard) OR the ISA-95 / Unified Namespace pattern if the user is going broader than Sparkplug.
Sparkplug B topic format (Eclipse Tahu spec):
spBv1.0/{group_id}/{message_type}/{edge_node_id}/{device_id}
Message types:
NBIRTH — Edge node online (publishes ALL metric definitions)
NDATA — Edge node metric value update
NDEATH — Edge node going offline (sent as LWT)
DBIRTH — Device online (under an edge node)
DDATA — Device metric value update
DDEATH — Device offline
NCMD — Inbound command to edge node
DCMD — Inbound command to deviceISA-95 / Unified Namespace pattern (for non-Sparkplug deployments):
{enterprise}/{site}/{area}/{line}/{cell}/{asset}/{metric}
e.g., acme/austin-plant/packaging/line-3/filler-2/torque
Reserve subtrees:
.../events — discrete state changes (Start, Stop, Alarm)
.../alarms — ISA-18.2 alarms
.../commands — write-back operationsGenerate topics.yaml documenting the chosen schema. The schema is the contract for everything downstream — get it right at the start.
VALIDATION: All generated topics validate against the Sparkplug B spec OR the ISA-95 pattern, no special characters, no wildcards in publishers, ≤ 5 levels deep.
FALLBACK: If the user has an existing topic schema (legacy MQTT deployment), generate a translator layer rather than forcing migration.
============================================================ === PHASE 2: BRIDGE CORE WITH SPARKPLUG LIFECYCLE === ============================================================
Generate the bridge code. Default to Python (best industrial library support). Use Node only if user requests it.
Required dependencies:
paho-mqtt (MQTT 5.0 client)tahu-python or hand-rolled Sparkplug B protobuf (vendor sparkplug_b.proto)asyncua for OPC UApymodbus for Modbuspylogix / pycomm3 / snap7 / pyads for direct PLCSparkplug B lifecycle implementation is non-negotiable:
# On startup:
1. Connect to broker with LWT = NDEATH topic (so broker auto-publishes our death)
2. Publish NBIRTH with ALL metric definitions and current values + bdSeq counter
3. For each device: publish DBIRTH with that device's metrics
4. Then start publishing DDATA on change
# On metric value change:
1. Increment seq number (0-255, wraps)
2. Publish DDATA with only the changed metrics (publish-on-change, NOT poll)
# On graceful shutdown:
1. Publish DDEATH for each device
2. Publish NDEATH for the edge node
3. Disconnect cleanly
# On broker reconnect:
1. Repeat NBIRTH/DBIRTH (consumers need fresh schema after death/birth)
2. Reset seq counter
3. Increment bdSeq (birth/death sequence — top-level continuity)Common bugs to PREVENT by construction:
VALIDATION: Run the bridge against a local HiveMQ + Sparkplug B Inspector (or Chariot Edge); confirm NBIRTH appears, DDATA flows, and DDEATH publishes on graceful shutdown. Pull the network cable and verify NDEATH appears via LWT.
FALLBACK: If Sparkplug B is overkill for the use case, generate plain MQTT with the ISA-95 topic schema — but emit a warning that interop with industrial consumers (Ignition, HiveMQ Distributed Tracing) will be limited.
============================================================ === PHASE 3: SECURITY & CERTIFICATE PROVISIONING === ============================================================
Generate the security stack. Defaults that ship to production:
Generate security/:
security/
├── ca/
│ ├── generate_ca.sh # one-time root CA generation
│ └── sign_client.sh # per-edge-node cert signing
├── certs/
│ └── .gitignore # certs NEVER committed
├── broker_acl.yaml # HiveMQ/EMQX ACL
└── README.md # rotation runbookVALIDATION: Bridge fails closed if cert is missing or expired (does NOT silently fall back to plaintext). ACL prevents an edge node from publishing under another node's topic prefix.
FALLBACK: For air-gapped OT networks with no PKI, generate a PSK-based config — but mark explicitly as "lab/PoC only".
============================================================ === PHASE 4: STORE-AND-FORWARD BUFFERING === ============================================================
OT networks drop. Bridges that don't buffer lose data. Generate a persistent queue (SQLite or RocksDB) that:
This is the difference between a hobby script and a production bridge.
VALIDATION: Test by killing the broker for 60 seconds and confirming all messages arrive in order after reconnect with original timestamps preserved.
============================================================ === PHASE 5: DOCKER-COMPOSE TEST RIG === ============================================================
Generate docker-compose.yml so the entire stack runs locally for testing:
services:
hivemq:
image: hivemq/hivemq4:latest
ports: ["1883:1883", "8883:8883", "8080:8080"]
volumes: [./security/certs:/opt/hivemq/conf/certs:ro]
modbus-sim: # mock PLC for testing
image: oitc/modbus-server:latest
opcua-sim:
image: opensimroot/opcua-server:latest
sparkplug-inspector:
image: cirruslink/sparkplug-inspector:latest
ports: ["3000:3000"]
bridge:
build: .
environment:
- MQTT_HOST=hivemq
- SOURCE_TYPE=opcua
- SOURCE_ENDPOINT=opc.tcp://opcua-sim:4840VALIDATION: docker-compose up brings up the full stack; Sparkplug Inspector at localhost:3000 shows the bridge's NBIRTH/DDATA flow within 30 seconds.
============================================================ === PHASE 6: OBSERVABILITY === ============================================================
Generate basic observability so failures don't hide:
/metrics): messages_published_total, broker_reconnects_total, queue_depth, cert_expiry_days_remaining./healthz) returning 200 only if broker is connected AND source protocol session is active.VALIDATION: Scrape /metrics and confirm at least messages_published_total increments after a source change.
============================================================ === SELF-REVIEW === ============================================================
Score 1–5:
Most common failure: forgetting to re-publish NBIRTH after reconnect → consumers see ghost edge nodes. Verify explicitly.
============================================================ === LEARNINGS CAPTURE === ============================================================
Append to ~/.claude/skills/iiot-bridge/LEARNINGS.md:
============================================================ === STRICT RULES === ============================================================
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.