Skip to main content

fakecloud_iotdata/
lib.rs

1//! AWS IoT Data Plane (`iotdata`) restJson1 service for fakecloud.
2//!
3//! The full 11-operation AWS IoT Data Plane Smithy model (SDK id
4//! `IoT Data Plane`, SigV4 signing name `iotdata`, endpoint prefix
5//! `data-ats.iot`). Every operation is a RESTful `<METHOD> <@http URI>` route
6//! with path labels (e.g. `POST /things/{thingName}/shadow`,
7//! `GET /retainedMessage/{topic}`, `POST /topics/{topic}`) so requests are
8//! routed by their HTTP method + `@http` URI template. Device-shadow and
9//! retained-message state is real, persisted, and account-partitioned.
10//!
11//! **Device shadows (classic + named).** `UpdateThingShadow` accepts a shadow
12//! document (`{"state":{"desired":…,"reported":…}}`) as the raw
13//! `@httpPayload` body, deep-merges `desired`/`reported` into the stored shadow
14//! (a `null` leaf deletes that key, matching AWS), bumps `version`, stamps
15//! per-leaf `metadata` timestamps, and recomputes `state.delta` (the subset of
16//! `desired` that differs from `reported`). `GetThingShadow` returns the full
17//! shadow document (state + delta + metadata + version + timestamp).
18//! `DeleteThingShadow` removes it and returns the deletion payload
19//! (`version` + `timestamp`). Named shadows are keyed by
20//! `(thingName, shadowName)` and behave identically;
21//! `ListNamedShadowsForThing` paginates a thing's named-shadow names with a
22//! round-tripping `nextToken`. A shadow-`version` conflict (the update carries
23//! a `version` that does not match the stored one) returns
24//! `ConflictException`. A missing shadow on GET/DELETE returns
25//! `ResourceNotFoundException`.
26//!
27//! **Publish + retained messages.** `Publish` accepts an MQTT message for a
28//! `topic` with `qos`/`retain` + a payload. When `retain=true` the message is
29//! stored so `GetRetainedMessage` / `ListRetainedMessages` reflect it (an empty
30//! retained payload clears the topic, matching AWS); a non-retained publish is
31//! accepted as a 200 no-op. `GetRetainedMessage` returns a stored message
32//! (payload, qos, `lastModifiedTime`); `ListRetainedMessages` paginates the
33//! retained-topic summaries.
34//!
35//! **Honest emulation choices (documented, not stubbed):**
36//! * fakecloud runs no MQTT broker, so `Publish` is accepted and — for
37//!   retained messages — stored, but is never fanned out to live subscribers.
38//!   There is no live pub/sub delivery.
39//! * Because there is no broker, no MQTT client is ever *connected*, so the
40//!   connection-introspection operations (`GetConnection`, `DeleteConnection`,
41//!   `ListSubscriptions`, `SendDirectMessage`) faithfully report
42//!   `ResourceNotFoundException` for every client id — the AWS-correct response
43//!   when no such connection exists. This is a real response reflecting the
44//!   emulated state, not a fabricated one.
45//! * Shadows are stored by `thingName` string; fakecloud does not require the
46//!   thing to pre-exist in an IoT Core registry.
47
48pub mod persistence;
49pub mod service;
50pub mod shared;
51pub mod state;
52mod validate;
53
54pub use service::{IotDataService, IOTDATA_ACTIONS};
55pub use state::{
56    IotDataData, IotDataSnapshot, SharedIotDataState, IOTDATA_SNAPSHOT_SCHEMA_VERSION,
57};