---
name: bridge-development
description: Build and package a customer CitusIO sink adapter using the installed public C Bridge SDK, wire it into a selected product profile and verify delivery, retry, drain and recovery.
---

# Build and package a bridge adapter

Use the public C SDK when the destination needs a custom client library or
delivery contract. It is available in every tier. Customers choose their own
compatible C toolchain and agent. Compile outside the runtime image; deploy a
library and configuration without adding a compiler or script runtime there.

Read [container setup](../container-setup/SKILL.md) for node placement and the
`integration-bridges` skill from the installed TOC when the selected tier
includes it. Lower tiers can use their installed sample and bridge-only topic
route; do not require rules/transformation features that are absent from the
selected profile. This skill grants no deployment authority.

## Establish the installed contract

Inspect the exact image, CPU/libc, public header and bridge binary. The installed
header is `/usr/local/include/nginz_iot/nginz_iot_bridge_sdk.h`; examples are
under `/usr/local/share/nginz-iot/bridge-sdk/examples/`. Match that exact header
and runtime rather than a floating source branch. The current public package
supports ABI v3 with unchanged v1/v2 compatibility. A small v1 one-event adapter
remains a valid starting point; select v3 for full event identity/idempotency.

The optional online [C tutorial](https://citusio.com/docs/operations/build-a-c-bridge)
and [starter files](https://citusio.com/examples/bridge-sdk/hello-world/README.txt)
provide a file-sink example. Installed examples remain available offline.

## Define the destination and package

Write down selected topics, exact input, payload handling, commitment point,
timeout, retryable/terminal outcomes, duplicate handling and drain behavior.
Keep credentials as private references. Use bounded calls and memory; retain
borrowed event/payload data only by copying it within its documented lifetime.

Implement negotiate/init/connect/send or send_batch/flush/drain/close/redact.
ABI v2/v3 batches are bounded to 32 events and 1 MiB. Validate structure sizes,
capabilities and required callbacks before claiming readiness. Use canonical
failure classes; never expose raw provider errors or secret-bearing config.
The host owns retries, backpressure, dead letters, health and durable replay.
Do not add another independent retry/replay owner inside the adapter.

Package the target-compatible `.so`, worker config, guardian target, topic
route and verification/operating notes. Mount the library/config read-only at
canonical trusted paths with safe owner/modes. Record a digest and configure
the expected hash where selected. One normal guardian supervises isolated
workers per target; the guardian does not load customer libraries. Native
isolation contains target faults but assumes trusted code and bounded host
resource use.

## Wire and verify

1. Validate the selected broker config and bridge worker config through their
   existing native `--test-config` interfaces. Match bridge IDs, route targets,
   namespaces and runtime directories; preserve container IPC/PID/network joins.
2. Start only the authorized selected roles and require fresh route/bridge
   readiness. Publish an isolated exact payload through the intended MQTT client.
3. Verify exact destination effects independently of MQTT ACKs. Exercise
   duplicate and ambiguous outcomes, timeout, retry/terminal classification,
   bounded backpressure, worker restart and clean drain in an owned test context.
4. For durable delivery, select the Pro-or-higher PostgreSQL outbox and verify
   replay against the same commitment/idempotency contract. Free permits real
   production use but keeps unsettled delivery state in memory.

Use [panel operations](../panel-operations/SKILL.md) or
[API operations](../admin-api-operations/SKILL.md) for redacted inspection.
Governed drain still requires matching live scope, verified role and fences;
acceptance stays pending until daemon reconciliation evidence arrives.

Hand off image/header/library hashes, ABI, package files, private input
references, exact provider/test scope, redacted results and the first unfinished
action. A sample compilation or local file sink does not qualify an arbitrary
provider or production deployment.
