Early · Apache-2.0 · Library

Shared backend
boilerplate
for any Rust app.

Configured clients and primitives — Postgres, Redis, crypto, storage, LLM, knowledge graph — feature-gated, logic-free. A library, not a server. You pick features; logic stays in your app.

Cargo.toml + main.rs — quick start
1# Cargo.toml — pick the features your service needs
2soma-infra = { path = "../soma-infra", features = ["db", "tracing"] }
3 
4// main.rs — two lines of setup, then your logic
5soma_infra::telemetry::init(); // RUST_LOG-aware
6let pool = soma_infra::connect_from_env().await?; // reads DATABASE_URL

One crate. Thirteen features.

Each concern is behind its own cargo feature. A db-only consumer never compiles the LLM or crypto graphs. Change one module, unrelated consumers don't rebuild.

db default

Postgres pool

connect_from_env() — a configured sqlx PgPool with sane defaults, sslmode support, and application_name.

tracing default

Structured logging

telemetry::init() — tracing-subscriber honouring RUST_LOG; human or LOG_FORMAT=json.

cache

Redis client

connect_from_env() — multiplexed, auto-reconnecting ConnectionManager; thin GET/SET/SETEX/DEL/EXPIRE helpers.

crypto

Crypto primitives

AES-256-GCM encrypt/decrypt, Argon2id password hashing, HKDF-SHA256, HMAC-SHA256, SHA-256. Caller supplies all parameters.

storage-s3

AWS S3 storage

StorageClient::from_env() — configured S3 (or S3-compatible) handle; thin get/put/delete.

storage-azure

Azure Blob storage

StorageClient::from_env() — configured Azure Blob handle; same thin API as storage-s3.

llm

Anthropic LLM client

LlmClient::from_env() — typed MessagesRequest/MessagesResponse + token usage. No retry, no prompt logic.

kg

Knowledge graph

Upsert nodes/edges, one-hop neighbor traversal, pgvector cosine-distance similarity search. No embedding generation.

http

HTTP client

client() — a reqwest::Client with rustls TLS and sane default timeouts (30s request, 10s connect).

signal

Graceful shutdown

shutdown_signal() — await Ctrl-C (SIGINT) or SIGTERM. Pure plumbing; does not log.

config

Env helpers

require_env / env_or / env_parse — tiny typed env-var helpers with clear error messages.

errors

Safe DB errors

redact_db_error — a client-safe message for a sqlx::Error. No SQL text, no bound params, no PII.

testing

Test harness

TestDb::create_from_env() — an isolated, auto-dropped Postgres database per test. Self-cleaning even on panic.

A library you use.
Not a service you run.

There is no binary, no daemon, no HTTP port. You add soma-infra as a Cargo dependency, select features, and call into configured clients from your own code.

Mechanism here

soma-infra

Pool builder, TLS setup, AES-256-GCM wire format, Argon2id PHC strings, HKDF/HMAC/SHA-256 math, object-store auth wiring, Anthropic wire protocol, pgvector query helpers, SIGTERM plumbing. Decision-free operations a service would otherwise hand-roll.

Policy in your app

Your service

KDF salt/info strings, which fields to encrypt, SQLSTATE→domain-error mapping, migration schema and advisory lock key, prompt construction and retry logic, object key naming, rate-limit backoff strategy, embedding generation, what to log on shutdown.

The rule: soma-infra ships the mechanism, never the policy. If a function makes a decision the service should own, it does not belong here.

Pick features. Call helpers.

Three representative snippets. See CONSUMING.md for the full per-module guide.

Database pool
1// Cargo.toml (default features include "db" + "tracing")
2soma-infra = { path = "../soma-infra" }
3 
4// main.rs
5soma_infra::telemetry::init();
6let pool = soma_infra::connect_from_env().await?;
Crypto primitives
1use soma_infra::crypto;
2 
3// Caller names the env var — that's your policy.
4let key = crypto::CryptoKey::from_env("CRYPTO_KEY")?;
5let ct = crypto::encrypt(&key, plaintext, aad)?;
6let dk = crypto::hkdf_sha256(ikm, Some(salt), info, 32)?;
Graceful shutdown + integration test
1// Graceful shutdown with axum
2axum::serve(listener, router)
3 .with_graceful_shutdown(soma_infra::signal::shutdown_signal())
4 .await?;
5 
6// Integration test with an isolated, auto-dropped DB
7let db = soma_infra::TestDb::create_from_env().await?;
8// ... use db.pool ... dropped + cleaned up automatically