# Rust SDK

Use AppContext, durable service clients, ingress envelopes, time, entropy, secrets, and constrained HTTP from Ferrite application code.

Ferrite applications depend on `ferrite-app`. The SDK exposes only the runtime
and capabilities available to constrained application code.

## Application entry point

```rust filename="src/main.rs"
#![forbid(unsafe_code)]

use std::io;
use ferrite_app::{app_main, AppContext, FerriteApp};

struct Worker;

impl FerriteApp for Worker {
    async fn run(ctx: AppContext) -> io::Result<()> {
        let mut jobs = ctx.queue("jobs")?;
        loop {
            let Some(lease) = jobs.poll_wait(1_000).await? else { continue };
            // Apply an idempotent effect before acknowledging the lease.
            jobs.ack(lease.token).await?;
        }
    }
}

fn main() { app_main::<Worker>() }
```

The handle passed to `ctx.queue("jobs")` must exist as a Queue binding in
`ferrite.json`. A missing or mismatched handle returns an error.

## Service handles

| SDK call | Use it for |
| --- | --- |
| `ctx.store("name")` | Linearizable key-value reads, writes, deletes, and compare-and-swap. |
| `ctx.ape("name")` | Guarded multi-key transactions. |
| `ctx.queue("name")` | Durable leased work, delayed delivery, acknowledgements, and retries. |
| `ctx.log("name")` | Ordered append and offset reads. |
| `ctx.topics("name")` | Named ordered streams within one binding. |
| `ctx.blob("name")` | Content-addressed object reads and writes. |
| `ctx.egress("name")` | Outbound HTTP to declared destination prefixes. |

## Ingress and replies

API routes publish an `IngressRequest` to the bound Queue. Decode the request,
apply the effect, publish an `IngressReply` to `req.reply_to`, and acknowledge
only after the reply publish succeeds.

```rust filename="src/api.rs"
use ferrite_app::{serde_json, AppContext, IngressReply, IngressRequest};

let request: IngressRequest = serde_json::from_slice(&lease.payload)?;
let reply = IngressReply {
    correlation_id: request.correlation_id.clone(),
    status: 200,
    headers: vec![("content-type".into(), "application/json".into())],
    body: br#"{"ok":true}"#.to_vec(),
};
let mut replies = ctx.reply_to_queue(&request.reply_to).await?;
replies.publish(&serde_json::to_vec(&reply)?).await?;
requests.ack(lease.token).await?;
```

## Platform utilities

Use `ctx.clock()` and `ctx.now_ms()` for injected time, `ctx.entropy()` for
cryptographic randomness, `ctx.secret("name")` for a declared secret, and
`ferrite_app::rt` for spawning, channels, sleep, interval, and timeout. The SDK
also provides JSON, tracing, password and action-token primitives, HMAC and
constant-time helpers, and safe response-cookie construction.

Continue with [App Manifest](/developers/app-manifest/) to bind services or
[Functions](/developers/functions/) for lifecycle and scaling.
