README.md

# LxmfEx

LXMF (Lightweight Extensible Message Format) for Elixir, interoperable with [markqvist/LXMF](https://github.com/markqvist/lxmf) and Reticulum. Provides message packing/unpacking, propagated store-and-forward, and a router with pluggable transport (works with `reticulum_ex`).

## Status

- Direct delivery uses Reticulum link-layer encryption (ECDH + AES-128).
- Propagated delivery is supported via destination-layer encryption (ECDH + Fernet-based token) in `reticulum_ex` NIF.
- Paper/QR support and full auto-peering to be completed.

## Installation

Add to your `mix.exs`:

```elixir
def deps do
  [
    {:lxmf_ex, "~> 0.1.0"},
    {:reticulum_ex, "~> 0.1.0"}
  ]
end
```

## Quick start

Start a router with the Reticulum transport and an identity for decrypting propagated messages:

```elixir
{:ok, id} = ReticulumEx.Identity.new_from_rand()
{:ok, router} = LxmfEx.Router.start_link(
  transport_mod: LxmfEx.Transport.Reticulum,
  storage_dir: "/tmp/lxmf_store",
  identity_ref: id,
  on_inbound: fn lxm -> IO.inspect({:inbound, lxm.title, lxm.content}) end
)

# Build a direct message
msg = LxmfEx.Message.new(
  destination_hash: <<dest::128>>, # 16-byte destination hash
  source_hash: <<src::128>>,        # 16-byte source hash
  title: "Hello",
  content: "World",
  method: :direct
)

hasher = fn iodata -> :crypto.hash(:sha256, IO.iodata_to_binary(iodata)) end
signer = fn data -> :crypto.hash(:sha512, data) |> binary_part(0, 64) end

{:ok, _} = LxmfEx.Router.send_message(router, msg, hasher, signer)
```

To send a propagated message, set `method: :propagated` on the message. Inbound propagated containers are decrypted using the router `:identity_ref`.

## Docs

HexDocs: https://hexdocs.pm/lxmf_ex

API highlights:
- `LxmfEx.Message`: LXM structure, `pack/3`, `unpack/1`.
- `LxmfEx.Router`: send/receive, propagated store, peering helpers.
- `LxmfEx.Transport`: behaviour; use `LxmfEx.Transport.Reticulum` in production.

## License

MIT. See `LICENSE`.