use affinidi_secrets_resolver::secrets::Secret;
use trust_tasks_https::{ClientError, HttpsClient};
use trust_tasks_proof::affinidi::SignOptions;
use trust_tasks_proof::ProofExt;
use trust_tasks_rs::{specs::acl::grant::v0_1 as grant, TrustTask};
pub(crate) fn demo_identity() -> (Secret, String) {
const SEED: [u8; 32] = [7u8; 32];
let throwaway = Secret::generate_ed25519(None, Some(&SEED));
let pk_mb = throwaway
.get_public_keymultibase()
.expect("ed25519 public multikey");
let vm = format!("did:key:{pk_mb}#{pk_mb}");
let mut secret = Secret::generate_ed25519(Some(&vm), Some(&SEED));
secret.id = vm.clone();
let did = vm.split('#').next().expect("did:key prefix").to_string();
(secret, did)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url = std::env::var("TRUST_TASKS_URL").unwrap_or_else(|_| "http://localhost:3000".into());
let (secret, my_did) = demo_identity();
let client = HttpsClient::builder()
.server_url(&url)
.server_vid("did:web:maintainer.example")
.my_vid(&my_did)
.my_token("alice")
.build()?;
let request = TrustTask::for_payload(
format!("urn:uuid:{}", uuid::Uuid::new_v4()),
grant::Payload {
entry: grant::AclEntry {
subject: "did:web:carol.example".into(),
role: "moderator".into(),
scopes: vec![],
allowed_keys: None,
label: Some("Carol — content moderation".into()),
created_at: None,
created_by: None,
updated_at: None,
updated_by: None,
expires_at: None,
approve: None,
step_up: None,
ext: None,
},
reason: Some("onboarding moderator".into()),
ext: None,
},
);
let mut request = request;
request.issuer = Some(my_did.clone());
request.recipient = Some("did:web:maintainer.example".into());
request.issued_at = Some(chrono::Utc::now());
request.sign(&secret, SignOptions::new()).await?;
println!(
"→ POST {}/trust-tasks\n request id: {}\n type: {}\n signed by: {}",
url, request.id, request.type_uri, my_did
);
match client
.send::<grant::Payload, grant::Response>(request)
.await
{
Ok(resp) => {
println!(
"← {} (id: {}, threadId: {})\n entry: subject={} role={}",
resp.type_uri,
resp.id,
resp.thread_id.as_deref().unwrap_or("<none>"),
resp.payload.entry.subject,
&*resp.payload.entry.role,
);
}
Err(ClientError::TrustTaskError { http_status, error }) => {
println!(
"← HTTP {} trust-task-error: code={} retryable={} message={:?}",
http_status, error.payload.code, error.payload.retryable, error.payload.message
);
}
Err(other) => return Err(other.into()),
}
Ok(())
}