Skip to main content

SimpleAgent

Struct SimpleAgent 

Source
pub struct SimpleAgent { /* private fields */ }
Expand description

A wrapper around the JACS Agent that provides a simplified, instance-based API.

This struct owns an Agent instance and provides methods for common operations like signing and verification. Unlike the deprecated module-level functions, SimpleAgent does not use global mutable state, making it thread-safe when used with appropriate synchronization.

§Narrow Contract (19 methods)

These are the ONLY public methods on SimpleAgent. This list is the single source of truth (Section 4.1.2 of ARCHITECTURE_UPGRADE.md). Advanced operations live in super::advanced, super::batch, etc.

#MethodPurpose
1createCreate agent with defaults
2create_with_paramsCreate agent with full control
3loadLoad existing agent from disk
4ephemeralCreate throwaway agent (no disk)
5verify_selfVerify own agent document signature
6sign_messageSign a JSON value
7sign_raw_bytesSign raw byte data
8sign_fileSign a file
9verifyVerify a signed document string
10verify_with_keyVerify with explicit public key
11verify_by_idVerify a stored document by ID
12export_agentExport agent identity JSON
13get_public_keyGet public key as raw bytes
14get_public_key_pemGet public key as PEM string
15get_agent_idGet agent ID
16key_idGet key ID
17diagnosticsRuntime diagnostic info
18is_strictCheck strict mode
19config_pathGet config file path

§Thread Safety

SimpleAgent uses interior mutability via Mutex to allow safe concurrent access to the underlying Agent. Multiple threads can share a SimpleAgent wrapped in an Arc.

§Example

use jacs::simple::SimpleAgent;
use std::sync::Arc;

// Create and share across threads
let agent = Arc::new(SimpleAgent::create("my-agent", None, None)?);

let agent_clone = Arc::clone(&agent);
std::thread::spawn(move || {
    let signed = agent_clone.sign_message(&serde_json::json!({"thread": 1})).unwrap();
});

Implementations§

Source§

impl SimpleAgent

Source

pub fn to_yaml(&self, json_str: &str) -> Result<String, JacsError>

Convert a JSON string to YAML.

This is a stateless convenience wrapper over convert::jacs_to_yaml.

Source

pub fn from_yaml(&self, yaml_str: &str) -> Result<String, JacsError>

Convert a YAML string to pretty-printed JSON.

This is a stateless convenience wrapper over convert::yaml_to_jacs.

Source

pub fn verify_yaml( &self, yaml_str: &str, ) -> Result<VerificationResult, JacsError>

Convert a YAML string to JSON and verify the document.

This is equivalent to calling from_yaml() followed by verify().

Source

pub fn to_html(&self, json_str: &str) -> Result<String, JacsError>

Convert a JSON string to a self-contained HTML document.

This is a stateless convenience wrapper over convert::jacs_to_html.

Source

pub fn from_html(&self, html_str: &str) -> Result<String, JacsError>

Extract JSON from an HTML document produced by to_html.

This is a stateless convenience wrapper over convert::html_to_jacs.

Source§

impl SimpleAgent

Source

pub fn is_strict(&self) -> bool

Returns whether this agent is in strict mode.

Source

pub fn key_id(&self) -> Result<String, JacsError>

Returns the JACS agent ID, used as the signing key identifier. Derived from the underlying Agent — no cached copy needed.

Source

pub fn create( name: &str, purpose: Option<&str>, key_algorithm: Option<&str>, ) -> Result<(Self, AgentInfo), JacsError>

Creates a new JACS agent with persistent identity.

This generates cryptographic keys, creates configuration files, and saves them to the current working directory.

§Arguments
  • name - Human-readable name for the agent
  • purpose - Optional description of the agent’s purpose
  • key_algorithm - Signing algorithm: “pq2025” (default), “ed25519”, or “rsa-pss”
§Returns

A SimpleAgent instance ready for use, along with AgentInfo containing the agent ID, name, and file paths.

§Files Created
  • ./jacs.config.json - Configuration file
  • ./jacs.agent.json - Signed agent identity (in jacs_data/agent/)
  • ./jacs_keys/ - Directory containing public and private keys
§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::create("my-agent", Some("Signing documents"), None)?;
println!("Agent created successfully");
Source

pub fn create_with_params( params: CreateAgentParams, ) -> Result<(Self, AgentInfo), JacsError>

Creates a new JACS agent with full programmatic control.

Unlike create(), this method accepts all parameters explicitly, making it suitable for non-interactive use from bindings and automation.

§Arguments
  • params - CreateAgentParams with all creation parameters
§Returns

A SimpleAgent instance and AgentInfo with the created agent’s details.

§Example
use jacs::simple::{SimpleAgent, CreateAgentParams};

let params = CreateAgentParams::builder()
    .name("my-agent")
    .password("MyStr0ng!Pass#2024")
    .algorithm("pq2025")
    .data_directory("/tmp/test_data")
    .key_directory("/tmp/test_keys")
    .config_path("/tmp/test.config.json")
    .build();

let (agent, info) = SimpleAgent::create_with_params(params)?;
Source

pub fn load( config_path: Option<&str>, strict: Option<bool>, ) -> Result<Self, JacsError>

Loads an existing agent from a configuration file.

§Arguments
  • config_path - Path to the configuration file (default: “./jacs.config.json”)
§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::load(None, None)?;  // Load from ./jacs.config.json
// or with strict mode:
let agent = SimpleAgent::load(Some("./my-agent/jacs.config.json"), Some(true))?;
Source

pub fn loaded_info(&self) -> Result<AgentInfo, JacsError>

Returns canonical metadata for the currently loaded agent.

Source

pub fn ephemeral( algorithm: Option<&str>, ) -> Result<(Self, AgentInfo), JacsError>

Creates an ephemeral in-memory agent. No config file, no directories, no environment variables, no password needed.

§Arguments
  • algorithm - Signing algorithm: “pq2025” (default), “ed25519”, or “rsa-pss”
§Returns

A SimpleAgent instance with in-memory keys, along with AgentInfo. Keys are lost when the agent is dropped.

§Example
use jacs::simple::SimpleAgent;

let (agent, info) = SimpleAgent::ephemeral(None)?;
let signed = agent.sign_message(&serde_json::json!({"hello": "world"}))?;
Source

pub fn verify_self(&self) -> Result<VerificationResult, JacsError>

Verifies the loaded agent’s own identity.

This checks:

  1. Self-signature validity
  2. Document hash integrity
  3. DNS TXT record (if domain is configured)
§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::load(None)?;
let result = agent.verify_self()?;
assert!(result.valid);
Source

pub fn sign_message(&self, data: &Value) -> Result<SignedDocument, JacsError>

Signs arbitrary data as a JACS message.

§IMPORTANT: Signing is Sacred

Signing a document is an irreversible, permanent commitment. Once signed:

  • The signature creates cryptographic proof binding you to the content
  • You cannot deny having signed (non-repudiation)
  • The signed document can be verified by anyone forever
  • You are accountable for the content you signed

Before signing, always:

  • Read and understand the complete document content
  • Verify the data represents your actual intent
  • Confirm you have authority to make this commitment

The data can be a JSON object, string, or any serializable value.

§Arguments
  • data - The data to sign (will be JSON-serialized)
§Returns

A SignedDocument containing the full signed document.

§Example
use jacs::simple::SimpleAgent;
use serde_json::json;

let agent = SimpleAgent::load(None)?;
// Review data carefully before signing!
let signed = agent.sign_message(&json!({"action": "approve", "amount": 100}))?;
println!("Document ID: {}", signed.document_id);
Source

pub fn sign_raw_bytes(&self, data: &[u8]) -> Result<Vec<u8>, JacsError>

Sign raw bytes and return the raw signature bytes.

This is a low-level signing method used by JACS email signing and other protocols that need to sign arbitrary data (not JSON documents). The data must be valid UTF-8 (JACS canonical payloads always are).

Returns the raw signature bytes (decoded from the base64 output of the underlying crypto module).

Source

pub fn get_agent_id(&self) -> Result<String, JacsError>

Get the JACS agent ID.

Returns the agent’s unique identifier from the exported agent JSON.

Source

pub fn set_storage(&self, storage: MultiStorage) -> Result<(), JacsError>

Replace the agent’s document storage backend.

After loading an agent from a filesystem config, call this with a "memory" backend to avoid filesystem writes for subsequent sign_message() / create_document_and_load() calls.

§Example
use jacs::storage::MultiStorage;

let agent = SimpleAgent::load(Some("./jacs.config.json"), None)?;
let mem = MultiStorage::new("memory".to_string())?;
agent.set_storage(mem)?;
// sign_message() now persists documents in-memory only
Source

pub fn sign_file( &self, file_path: &str, embed: bool, ) -> Result<SignedDocument, JacsError>

Signs a file with optional content embedding.

§IMPORTANT: Signing is Sacred

Signing a file is an irreversible, permanent commitment. Your signature:

  • Cryptographically binds you to the file’s exact contents
  • Cannot be revoked or denied (non-repudiation)
  • Creates permanent proof that you attested to this file
  • Makes you accountable for the file content forever

Before signing any file:

  • Review the complete file contents
  • Verify the file has not been tampered with
  • Confirm you intend to attest to this specific file
  • Understand your signature is permanent and verifiable
§Arguments
  • file_path - Path to the file to sign
  • embed - If true, embed file content; if false, store only hash reference
§Returns

A SignedDocument containing the signed file reference or embedded content.

§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::load(None)?;

// Review file before signing! Embed the file content
let signed = agent.sign_file("contract.pdf", true)?;

// Or just reference it by hash
let signed = agent.sign_file("large-video.mp4", false)?;
Source

pub fn verify( &self, signed_document: &str, ) -> Result<VerificationResult, JacsError>

Verifies a signed document and extracts its content.

This function auto-detects whether the document contains a message or file.

§Arguments
  • signed_document - The JSON string of the signed document
§Returns

A VerificationResult with the verification status and extracted content.

§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::load(None)?;
let result = agent.verify(&signed_json)?;
if result.valid {
    println!("Content: {}", result.data);
} else {
    println!("Verification failed: {:?}", result.errors);
}
Source

pub fn verify_with_key( &self, signed_document: &str, public_key: Vec<u8>, ) -> Result<VerificationResult, JacsError>

Verifies a signed JACS document using a provided public key.

This is identical to verify() but uses the supplied public_key bytes instead of the agent’s own key. This allows any agent to verify documents signed by a different agent, given the signer’s public key (e.g., from a registry or trust store).

§Arguments
  • signed_document - The JSON string of the signed JACS document
  • public_key - The signer’s public key bytes (PEM file content)
§Example
// agent_b verifies a document that agent_a signed
let result = agent_b.verify_with_key(&signed_doc, agent_a_pubkey)?;
if result.valid {
    println!("Verified: signed by {}", result.signer_id);
}
Source

pub fn verify_by_id( &self, document_id: &str, ) -> Result<VerificationResult, JacsError>

Verifies a signed document looked up by its document ID from storage.

This is a convenience method for when you have a document ID (e.g., “uuid:version”) rather than the full JSON string.

§Arguments
  • document_id - The document ID in “uuid:version” format
§Example
use jacs::simple::SimpleAgent;

let agent = SimpleAgent::load(None)?;
let result = agent.verify_by_id("abc123:1")?;
assert!(result.valid);
Source

pub fn export_agent(&self) -> Result<String, JacsError>

Exports the agent’s identity JSON for P2P exchange.

Source

pub fn get_public_key(&self) -> Result<Vec<u8>, JacsError>

Returns the agent’s public key bytes from memory.

This returns the raw public key bytes as stored in the agent’s internal state. The format depends on the algorithm (e.g., raw 32 bytes for Ed25519, PEM for RSA-PSS). These bytes are the same format expected by verify_with_key() and verify_document_signature().

Source

pub fn get_public_key_pem(&self) -> Result<String, JacsError>

Returns the agent’s public key in PEM format.

Source

pub fn diagnostics(&self) -> Value

Returns diagnostic information including loaded agent details.

Source

pub fn config_path(&self) -> Option<&str>

Returns the path to the configuration file, if available.

Trait Implementations§

Source§

impl JacsSigner for SimpleAgent

Source§

fn sign_message(&self, data: &Value) -> Result<SignedDocument, JacsError>

Create a signed JACS document from the given content. Read more
Source§

fn verify_with_key( &self, signed_document: &str, public_key: Vec<u8>, ) -> Result<VerificationResult, JacsError>

Verify a signed JACS document using the provided public key. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more