ma_core/lib.rs
1//! # ma-core
2//!
3//! A lean `DIDComm` service library for the ma ecosystem.
4//!
5//! `ma-core` provides the building blocks for ma-capable endpoints:
6//!
7//! - **DID documents** — create, validate, resolve, and publish `did:ma:` documents
8//! to IPFS/IPNS (via Kubo on native targets). Use [`MaExtension`] to build the
9//! `ma:` extension field, and [`config::SecretBundle::build_document`] (`config`
10//! feature) as the single entry point for a complete, signed document.
11//! - **Service inboxes** — bounded, TTL-aware FIFO queues ([`Inbox`])
12//! for receiving validated messages on named protocol services.
13//! - **Outbound sending** — fire-and-forget delivery of validated [`Message`] objects
14//! to remote endpoints, serialized to CBOR on the wire.
15//! - **Endpoint abstraction** — the [`MaEndpoint`] trait with pluggable
16//! transport backends.
17//! - **Transport parsing** — extract endpoint IDs and protocols from DID document
18//! service strings (`/iroh/<id>/<protocol>`).
19//! - **Identity bootstrap** — secure secret key generation and persistence.
20//!
21//! ## Services
22//!
23//! Every endpoint must provide `/ma/inbox/0.0.1` (the default inbox).
24//! Endpoints may optionally provide `ma/ipfs/0.0.1` to publish DID documents
25//! on behalf of others.
26//!
27//! ## Feature flags
28//!
29//! - **`kubo`** — enables native IPFS RPC backend for publishing (native only).
30//! - **`iroh`** — enables the internal iroh QUIC transport backend.
31//! - **`config`** — enables [`Config`], [`SecretBundle`], and [`MaArgs`] for
32//! YAML-based daemon configuration, encrypted secret bundles, and CLI
33//! argument parsing. Also provides [`config::SecretBundle::build_document`] and
34//! [`config::SecretBundle::signing_key`] for constructing ready-to-publish DID documents.
35//!
36//! ## Platform support
37//!
38//! Core types (`Inbox`, `Service`, transport parsing, validation)
39//! compile on all targets including `wasm32-unknown-unknown`.
40//!
41//! ### wasm vs native
42//!
43//! - `ma-core` supports both wasm and native targets.
44//! - `IpfsGatewayResolver` (HTTP gateway DID fetch) is available on wasm and native.
45//! - Native IPFS RPC write/pin APIs are native-only (`not(wasm32)` + `kubo` feature).
46//! - wasm builds expose only `ipfs::gateway_resolver` (no native RPC helpers).
47//! - `config` serialization and `SecretBundle` crypto work on wasm.
48//! - `config` filesystem paths, CLI/env merging, and file I/O are native-only.
49//! - If your wasm application needs native IPFS RPC write/pin operations, provide
50//! them in a native companion layer.
51
52#![forbid(unsafe_code)]
53#![allow(
54 clippy::cast_possible_truncation,
55 clippy::cast_precision_loss,
56 clippy::if_not_else,
57 clippy::items_after_statements,
58 clippy::manual_let_else,
59 clippy::map_unwrap_or,
60 clippy::missing_errors_doc,
61 clippy::must_use_candidate,
62 clippy::uninlined_format_args
63)]
64
65#[cfg(feature = "acl")]
66pub mod acl;
67#[cfg(feature = "config")]
68pub mod config;
69pub mod constants;
70pub mod did;
71pub mod doc;
72pub mod endpoint;
73pub mod error;
74pub mod identity;
75pub mod inbox;
76pub mod interfaces;
77pub mod ipfs;
78#[cfg(feature = "iroh")]
79#[allow(dead_code)]
80mod iroh;
81pub mod key;
82#[cfg(all(feature = "kubo", not(target_arch = "wasm32")))]
83mod kubo;
84#[cfg(all(feature = "kubo", not(target_arch = "wasm32")))]
85pub use kubo::{cat_bytes, ipfs_add};
86pub mod msg;
87mod multiformat;
88#[cfg(feature = "iroh")]
89#[allow(dead_code)]
90mod outbox;
91pub mod service;
92pub mod transport;
93pub(crate) mod ttl_queue;
94
95// ─── Re-export DID/message primitives ───────────────────────────────────────
96
97pub use did::{Did, DID_PREFIX};
98pub use doc::{
99 now_iso_utc, Document, MaExtension, Proof, VerificationMethod, DEFAULT_DID_CONTEXT,
100 DEFAULT_PROOF_PURPOSE, DEFAULT_PROOF_TYPE,
101};
102pub use error::{Error, MaError, Result};
103pub use identity::{
104 generate_identity, generate_identity_from_secret, ipns_from_secret, GeneratedIdentity,
105};
106pub use ipld_core::ipld::Ipld;
107pub use key::{
108 EncryptionKey, SigningKey, ASSERTION_METHOD_KEY_TYPE, CODEC_ED25519_PUB, CODEC_EDDSA_SIG,
109 CODEC_X25519_PUB, KEY_AGREEMENT_KEY_TYPE,
110};
111pub use msg::{
112 decode_content, encode_content, Envelope, Headers, Message, ReplayGuard,
113 DEFAULT_MAX_CLOCK_SKEW_SECS, DEFAULT_MESSAGE_TTL_SECS, DEFAULT_REPLAY_WINDOW_SECS,
114 MESSAGE_PREFIX,
115};
116pub use multiformat::{
117 CODEC_CBOR, CODEC_DAG_CBOR, CODEC_DAG_JSON, CODEC_IDENTITY, CODEC_JSON, CODEC_RAW,
118};
119
120#[cfg(feature = "acl")]
121pub use acl::{
122 check_cap, is_principal_key, is_valid_acl_key, normalize_principal, validate_acl_map, AclMap,
123 CapabilityEntry, CAP_ACL, CAP_CREATE, CAP_CRUD, CAP_DELETE, CAP_INBOX, CAP_IPFS, CAP_READ,
124 CAP_RPC, CAP_UPDATE, GROUP_PREFIX, LOCAL_ENTITY_WILDCARD,
125};
126
127// ─── Re-export service constants ────────────────────────────────────────────
128
129pub use service::{
130 Service, CONTENT_TYPE_CBOR, CONTENT_TYPE_TERM, CONTENT_TYPE_TERM_CBOR,
131 CONTENT_TYPE_TERM_DAG_CBOR, CONTENT_TYPE_TERM_YAML, CRUD_PROTOCOL_ID, INBOX_PROTOCOL_ID,
132 IPFS_PROTOCOL_ID, MESSAGE_TYPE_BROADCAST, MESSAGE_TYPE_CHAT, MESSAGE_TYPE_CRUD,
133 MESSAGE_TYPE_CRUD_REPLY, MESSAGE_TYPE_DOC, MESSAGE_TYPE_EMOTE, MESSAGE_TYPE_IPFS_REQUEST,
134 MESSAGE_TYPE_IPFS_STORE, MESSAGE_TYPE_MESSAGE, MESSAGE_TYPE_RPC, MESSAGE_TYPE_RPC_REPLY,
135 RPC_PROTOCOL_ID,
136};
137
138// ─── Re-export Inbox ────────────────────────────────────────────────────────
139
140pub use inbox::Inbox;
141
142// ─── Re-export endpoint trait and implementations ───────────────────────────
143
144pub use endpoint::{MaEndpoint, DEFAULT_DELIVERY_PROTOCOL_ID};
145#[cfg(feature = "iroh")]
146pub use outbox::Outbox;
147
148/// Create a default ma endpoint backend from 32-byte secret key material.
149///
150/// This keeps the transport backend type internal while exposing
151/// [`MaEndpoint`] and [`Outbox`] as stable API surfaces.
152#[cfg(feature = "iroh")]
153pub async fn new_ma_endpoint(secret_bytes: [u8; 32], ipv6: bool) -> Result<Box<dyn MaEndpoint>> {
154 let endpoint = iroh::new_endpoint(secret_bytes, ipv6).await?;
155 Ok(Box::new(endpoint))
156}
157
158// ─── Re-export transport parsing ────────────────────────────────────────────
159
160pub use transport::{
161 endpoint_id_from_transport, endpoint_id_from_transport_value, normalize_endpoint_id,
162 protocol_from_transport, resolve_endpoint_for_protocol, resolve_inbox_endpoint_id,
163 transport_string,
164};
165
166// ─── Re-export identity helpers ─────────────────────────────────────────────
167
168pub use identity::{generate_secret_key_file, load_secret_key_bytes, socket_addr_to_multiaddr};
169
170// ─── Re-export config types ──────────────────────────────────────────────────
171
172#[cfg(all(feature = "config", not(target_arch = "wasm32")))]
173pub use config::MaArgs;
174#[cfg(feature = "config")]
175pub use config::{BrowserIdentityExport, Config, SecretBundle};
176
177// ─── Re-export DID resolution ───────────────────────────────────────────────
178
179pub use ipfs::gateway_resolver::{DidDocumentResolver, IpfsGatewayResolver};
180
181// ─── Re-export existing modules ─────────────────────────────────────────────
182
183pub use interfaces::{DidPublisher, IpfsPublisher};
184pub use ipfs::*;