Granit.IoT Bundle Reference
The two meta-bundles ship the full Granit.IoT stack as single NuGet references — one for the cloud-agnostic core, one for the AWS bridge family. Teams can onboard IoT device management, telemetry ingestion, threshold alerts, background jobs, the audit timeline, the MCP bridge for AI assistants, and (optionally) the full AWS IoT Core bridge without hand-picking 18 packages.
Granit.Bundle.IoT — cloud-agnostic stack (12 packages)
Section titled “Granit.Bundle.IoT — cloud-agnostic stack (12 packages)”When to use the bundle
Section titled “When to use the bundle”Use Granit.Bundle.IoT when:
- You want the full Ring 1 + Ring 2 + Ring 3 stack wired up with sensible defaults
- You’re starting a new greenfield Granit application
- You don’t need to cherry-pick a subset (e.g. ingestion without endpoints)
Use individual packages when:
- You only need the domain (tests, shared libraries)
- You want to swap the EF Core layer for a custom persistence adapter
- You’re integrating with an alternative web framework that doesn’t use Minimal API
What’s inside
Section titled “What’s inside”| # | Package | Ring | Role |
|---|---|---|---|
| 1 | Granit.IoT | 1 | Domain, value objects, events, CQRS abstractions |
| 2 | Granit.IoT.EntityFrameworkCore | 1 | IoTDbContext, EF Core configurations |
| 3 | Granit.IoT.EntityFrameworkCore.Postgres | 1 | PostgreSQL migrations (BRIN, GIN, partitioning) |
| 4 | Granit.IoT.Endpoints | 1 | Device CRUD + telemetry queries |
| 5 | Granit.IoT.BackgroundJobs | 1 | Purge, heartbeat, partition maintenance |
| 6 | Granit.IoT.Ingestion | 2 | Provider-agnostic ingestion pipeline |
| 7 | Granit.IoT.Ingestion.Endpoints | 2 | POST /iot/ingest/{source} webhook |
| 8 | Granit.IoT.Ingestion.Scaleway | 2 | Scaleway IoT Hub provider |
| 9 | Granit.IoT.Wolverine | 2 | Wolverine handlers + threshold evaluation |
| 10 | Granit.IoT.Notifications | 3 | Bridge to Granit.Notifications |
| 11 | Granit.IoT.Timeline | 3 | Bridge to Granit.Timeline |
| 12 | Granit.IoT.Mcp | 3 | Read-only [McpServerTool] wrappers for AI assistants |
flowchart LR B["Granit.Bundle.IoT<br/>(meta-package)"] B --> R1["Ring 1<br/>5 packages"] B --> R2["Ring 2<br/>4 packages"] B --> R3["Ring 3<br/>3 bridges"]
Not included — these are opt-in
Section titled “Not included — these are opt-in”Granit.IoT.Mqtt+Granit.IoT.Mqtt.Mqttnet— add only if you need to consume from a non-Scaleway MQTT broker. See MQTT transport.Granit.IoT.EntityFrameworkCore.Timescale— opt-in TimescaleDB backend. See Time-series storage.Granit.IoT.Ingestion.Aws— AWS-native ingestion provider (SNS / Direct / API Gateway). Not bundled inGranit.Bundle.IoT.Aws(which covers the device-binding side); add it explicitly withdotnet add package Granit.IoT.Ingestion.Awswhen you want AWS-shaped telemetry instead of (or alongside) the Scaleway webhook.Granit.IoT.Awsfamily (6 packages — provisioning, shadow, jobs, JITP) — useGranit.Bundle.IoT.Awson top.
Installation
Section titled “Installation”dotnet add package Granit.Bundle.IoTThis single reference transitively pulls in all 12 bundled packages. No
dependency conflicts — every package in the bundle targets the same
Granit.* framework version pinned in Directory.Packages.props.
Registration
Section titled “Registration”using Granit.Bundle.IoT;
builder.Services .AddGranit(builder.Configuration) .AddIoT();
app.MapGranitIoTEndpoints(); // /iot/devices + /iot/telemetryapp.MapGranitIoTIngestionEndpoints(); // /iot/ingest/{source}AddIoT() enumerates the 11 active modules in topological order
(Granit.IoT.EntityFrameworkCore.Postgres ships as helpers only, so it has
no module class to register). Actual DI registration is driven by each
module’s [DependsOn(...)] graph — the bundle’s enumeration is just a
complete list, so dependency order is never a concern.
What you get out of the box
Section titled “What you get out of the box”After AddIoT():
- Device CRUD endpoints at
/iot/devices(permissions, FluentValidation, OpenAPI) - Telemetry query endpoints at
/iot/telemetry/{deviceId} - Scaleway webhook at
/iot/ingest/scaleway(HMAC + Redis dedup + Wolverine outbox) - Three recurring background jobs (purge, heartbeat, partition maintenance)
- Two notification types (threshold alert + device offline) auto-registered
- Device lifecycle → timeline audit chatter
- Four read-only MCP tools (
iot_list_devices,iot_get_device,iot_query_telemetry,iot_get_latest_readings) — see MCP bridge - OpenTelemetry metrics for every stage (see Operations — Observability)
→ Already wired? Walk through it end-to-end on Getting started.
Breaking down the bundle if you need to
Section titled “Breaking down the bundle if you need to”If the bundle is “too much,” register only what you need — each module’s DI extension is public:
builder.Services .AddGranitIoT() // domain only .AddGranitIoTEntityFrameworkCore() // persistence .AddGranitIoTEndpoints(); // CRUD API// skip ingestion / wolverine / jobs / bridgesThe module system enforces ring discipline — you can’t accidentally register a Ring 3 bridge without its Ring 2 producer. Architecture tests catch violations at build time.
Granit.Bundle.IoT.Aws — AWS IoT Core bridge (6 packages)
Section titled “Granit.Bundle.IoT.Aws — AWS IoT Core bridge (6 packages)”The opt-in companion bundle for hosts targeting AWS IoT Core. Add on top
of Granit.Bundle.IoT — the core stack stays cloud-agnostic.
What’s inside
Section titled “What’s inside”| # | Package | Role |
|---|---|---|
| 1 | Granit.IoT.Aws | Companion AwsThingBinding, ThingName VO, IAwsIoTCredentialProvider |
| 2 | Granit.IoT.Aws.EntityFrameworkCore | Isolated AwsBindingDbContext (iotaws_* schema) |
| 3 | Granit.IoT.Aws.Provisioning | IAmazonIoT + Secrets Manager, idempotent provisioning saga |
| 4 | Granit.IoT.Aws.Shadow | Device Shadow sync (reported push + delta polling) |
| 5 | Granit.IoT.Aws.Jobs | IDeviceCommandDispatcher backed by AWS IoT Jobs |
| 6 | Granit.IoT.Aws.FleetProvisioning | JITP endpoints + claim cert rotation |
Installation
Section titled “Installation”dotnet add package Granit.Bundle.IoT.AwsRegistration
Section titled “Registration”builder.Services .AddGranit(builder.Configuration) .AddIoT() // cloud-agnostic core .AddGranitBundleIoTAws(o => o.UseNpgsql(connectionString)); // AWS bridge familyFull deep dive: AWS IoT Core bridge.
Versioning
Section titled “Versioning”The bundles track the Granit.IoT release cycle. Pre-release
(pre-v1.0.0), breaking changes land in minor versions; post-v1.0.0,
SemVer applies strictly. The current compatibility matrix lives on the
releases page — that’s
the authoritative source for the Granit.IoT ↔ Granit framework ↔ .NET ↔ EF Core matrix.
See also
Section titled “See also”- Getting started — 5-minute quickstart using
Granit.Bundle.IoT - Overview — ring structure and design decisions
- MQTT transport — the one package group not in the bundle (opt-in)
- AWS IoT Core bridge —
Granit.Bundle.IoT.Awsdeep dive