use serde::de::DeserializeOwned;
use serde_json::{Value, json};
use std::collections::{BTreeSet, HashMap};
use trust_tasks_rs::specs;
use trust_tasks_rs::validate::ValidatedPayload;
use vta_sdk::trust_tasks as uris;
use vta_sdk::acl::ContextDirection;
use vta_sdk::keys::{KeyOrigin, KeyRecord, KeyStatus, KeyType};
use vta_sdk::protocols::acl_management::change_role::ChangeRoleBody;
use vta_sdk::protocols::acl_management::create::{CreateAclBody, CreateAclResponseBody};
use vta_sdk::protocols::acl_management::delete::{DeleteAclBody, DeleteAclResultBody};
use vta_sdk::protocols::acl_management::entry::{AclEntry, Approve, StepUp};
use vta_sdk::protocols::acl_management::get::{GetAclBody, GetAclResultBody};
use vta_sdk::protocols::acl_management::list::{ListAclBody, ListAclResultBody};
use vta_sdk::protocols::acl_management::swap::{SwapKeyBody, SwapKeyResultBody};
use vta_sdk::protocols::acl_management::update::UpdateAclBody;
use vta_sdk::protocols::app_state::{
AppStateDeleteBody, AppStateDeleteResponse, AppStateGetBody, AppStateGetManyBody,
AppStateGetManyResponse, AppStateGetResponse, AppStateListBody, AppStateListResponse,
AppStatePutBody, AppStatePutManyBody, AppStatePutManyResponse, AppStatePutResponse,
AppStateRecord, AppStateWrite, PutManyMode, WriteOutcome, WriteResult,
};
use vta_sdk::protocols::audit_management::list::{
AuditEnvelope, ListAuditLogsBody, ListAuditLogsResultBody,
};
use vta_sdk::protocols::auth::{RevokeSessionRequest, RevokeSessionResponse};
use vta_sdk::protocols::consent_management::{
ConsentApproverListBody, ConsentApproverSetBody, ConsentDecisionBody, ConsentListBody,
ConsentRequestBody, ConsentRevokeBody,
};
use vta_sdk::protocols::credential_exchange::{
self as credx, PendingApproveBody, PendingDenyBody, PendingDenyResponse, PendingListResponse,
PendingPresentationSummary, PresentBody, RequestedCredentialSummary,
};
use vta_sdk::protocols::credentials_issuance::{
IssueCredentialBody, IssueCredentialResponse, RevokeCredentialBody, RevokeCredentialResponse,
};
use vta_sdk::protocols::device_management::{
DeviceDisableBody, DeviceHeartbeatBody, DeviceRegisterBody, DeviceSetWakeBody, DeviceWipeBody,
WakeHandle,
};
use vta_sdk::protocols::did_management::servers::{
AgentOnlyDid, HostOnlyDid, ListWebvhServerDomainsBody, ListWebvhServerDomainsResultBody,
ReconcileWebvhServerDidsBody, ReconcileWebvhServerDidsResultBody, RetireOrphanSlotBody,
RetireOrphanSlotResultBody, WebvhServerDomainEntry,
};
use vta_sdk::protocols::key_management::create::{
CreateKeyBody, CreateKeyResponseBody, CreateKeyResultBody,
};
use vta_sdk::protocols::key_management::derive_and_sign::{
DeriveAndSignBody, DeriveAndSignResultBody,
};
use vta_sdk::protocols::key_management::derive_and_sign_document::{
DeriveAndSignDocumentBody, DeriveAndSignDocumentResultBody,
};
use vta_sdk::protocols::key_management::get::{GetKeyBody, GetKeyResponseBody};
use vta_sdk::protocols::key_management::import::ImportKeyBody;
use vta_sdk::protocols::key_management::list::{ListKeysBody, ListKeysResultBody};
use vta_sdk::protocols::key_management::rename::{RenameKeyBody, RenameKeyResultBody};
use vta_sdk::protocols::key_management::revoke::{RevokeKeyBody, RevokeKeyResultBody};
use vta_sdk::protocols::key_management::sign::{SignAlgorithm, SignRequestBody, SignResultBody};
use vta_sdk::protocols::memory::{
MemoryDeleteBody, MemoryDeleteResponse, MemoryItem, MemoryListBody, MemoryListResponse,
MemoryPutBody, MemoryPutResponse,
};
use vta_sdk::protocols::policy_management::{
DeletePolicyBody, DeletePolicyResultBody, GetPolicyBody, GetPolicyResultBody, ListPoliciesBody,
ListPoliciesResultBody, PolicyModuleView, UpsertPolicyBody, UpsertPolicyResultBody,
};
use vta_sdk::protocols::vault_management::VaultUpsertBody;
use vta_sdk::protocols::vta_management::get_config::{
ConfigField, GetConfigBody, GetConfigResultBody,
};
use vta_sdk::protocols::vta_management::update_config::{
RejectedKey, UpdateConfigBody, UpdateConfigResultBody,
};
use super::dispatched_uris;
fn resolved_uris() -> BTreeSet<&'static str> {
dispatched_uris()
.into_iter()
.filter(|u| trust_tasks_rs::schema_index::schema_for(u).is_some())
.collect()
}
type ParseFn = fn(Value) -> Result<(), String>;
type ValidateFn = fn(&Value) -> Result<(), String>;
fn parses<T: DeserializeOwned>(v: Value) -> Result<(), String> {
serde_json::from_value::<T>(v)
.map(|_| ())
.map_err(|e| e.to_string())
}
fn validates<T: ValidatedPayload>(v: &Value) -> Result<(), String> {
T::validate_value(v).map_err(|e| e.to_string())
}
struct Witness {
request: Value,
parse_request: ParseFn,
validate_request: ValidateFn,
response: Value,
parse_response: ParseFn,
}
enum Conformance {
Checked(Witness),
#[allow(dead_code)] KnownDrift(&'static str),
}
macro_rules! checked {
($p:ty, $r:ty, $req:expr, $resp:expr) => {
Conformance::Checked(Witness {
request: $req,
parse_request: parses::<$p>,
validate_request: validates::<$p>,
response: $resp,
parse_response: parses::<$r>,
})
};
}
const SUBJECT: &str = "did:key:z6MkSubject";
const DIGEST_MULTIBASE: &str = "zQmSK9pGKFnmc77pqyNAPJyPKt8rMqctngfg3vwuMArwGYZ";
const TS: &str = "2026-07-29T00:00:00Z";
fn dt() -> chrono::DateTime<chrono::Utc> {
chrono::DateTime::parse_from_rfc3339(TS)
.expect("valid ts")
.with_timezone(&chrono::Utc)
}
fn app_state_record() -> AppStateRecord {
AppStateRecord {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/acme".into(),
version: 52,
deleted: false,
value: Some(serde_json::json!({ "label": "Acme", "role": "admin" })),
value_bytes: Some(95),
created_at: Some(TS.into()),
updated_at: TS.into(),
deleted_at: None,
}
}
fn app_state_tombstone() -> AppStateRecord {
AppStateRecord {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/defunct".into(),
version: 44,
deleted: true,
value: None,
value_bytes: None,
created_at: Some(TS.into()),
updated_at: TS.into(),
deleted_at: Some(TS.into()),
}
}
fn declarative_module() -> String {
vta_sdk::approvals::synthesize_rego(&[vta_sdk::approvals::ApprovalRule::reauth(
uris::TASK_ACL_GRANT_0_1,
)])
}
fn declarative_ext() -> Value {
json!({
vta_sdk::approvals::EXT_KEY_RULES: [
{ "taskType": uris::TASK_ACL_GRANT_0_1, "requires": "reauth" }
],
vta_sdk::approvals::EXT_KEY_APPROVER_SETS: {},
})
}
fn policy_module_view() -> PolicyModuleView {
PolicyModuleView {
id: "approvals".into(),
name: "Declarative approvals".into(),
description: Some("Declarative approval rules".into()),
module: declarative_module(),
applies_to: vec![],
priority: vta_sdk::approvals::DECLARATIVE_POLICY_PRIORITY,
enabled: true,
version: 2,
created_at: TS.into(),
updated_at: TS.into(),
ext: declarative_ext(),
}
}
fn key_record() -> KeyRecord {
KeyRecord {
key_id: "app-signing-key".into(),
derivation_path: "m/26'/2'/0'/1'".into(),
key_type: KeyType::Ed25519,
status: KeyStatus::Active,
public_key: "z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH".into(),
label: Some("app signing key".into()),
context_id: Some("app".into()),
seed_id: Some(1),
origin: KeyOrigin::Derived,
created_at: dt(),
updated_at: dt(),
}
}
fn key_result() -> CreateKeyResultBody {
CreateKeyResultBody {
key_id: "app-signing-key".into(),
key_type: KeyType::Ed25519,
derivation_path: "m/26'/2'/0'/1'".into(),
public_key: "z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH".into(),
status: KeyStatus::Active,
label: Some("app signing key".into()),
origin: KeyOrigin::Derived,
created_at: dt(),
}
}
fn acl_entry() -> AclEntry {
AclEntry {
subject: SUBJECT.into(),
role: "reader".into(),
scopes: vec!["ctx-a".into()],
label: Some("build agent".into()),
created_at: Some(dt()),
created_by: Some("did:key:z6MkAdmin".into()),
updated_at: Some(dt()),
updated_by: Some("did:key:z6MkAdmin".into()),
expires_at: Some(dt()),
step_up: Some(StepUp {
approver: Some("did:key:z6MkApprover".into()),
require: Some("delegated".into()),
}),
approve: Some(Approve {
all: false,
scopes: vec!["ctx-a".into()],
}),
allowed_keys: Some(vec!["tenant-key-a".into()]),
}
}
fn to_v<T: serde::Serialize>(t: T) -> Value {
serde_json::to_value(t).expect("serialize fixture")
}
fn session_json() -> Value {
json!({
"id": "sess-1",
"subject": SUBJECT,
"issuedAt": TS,
"expiresAt": TS,
"amr": ["swk"],
"acr": "aal2",
})
}
fn device_binding_json() -> Value {
json!({
"deviceId": "dev-1",
"consumerKind": { "kind": "companion", "formFactor": "browser" },
"displayName": "Laptop",
"registeredAt": TS,
"consumerDid": SUBJECT,
"platform": "macOS",
"pushCapable": false,
})
}
fn consent_subject_json() -> Value {
json!({
"platform": "slack",
"conversationRef": "conv-9f3",
"kind": "dm",
"agent": "agent-1",
})
}
fn vault_entry() -> vti_common::vault::VaultEntry {
use vti_common::vault::{SecretKind, SiteTarget, VaultEntry};
VaultEntry {
id: "01HVAULTENTRY".into(),
context_id: "ctx-a".into(),
targets: vec![SiteTarget::WebOrigin {
origin: "https://example.com".into(),
}],
label: "example.com login".into(),
secret_kind: SecretKind::Password,
tags: vec!["work".into()],
notes: Some("shared team login".into()),
favicon: None,
selectors: vec![],
custom_field_names: vec![],
attachments: vec![],
expires_at: Some(TS.into()),
breached_at: None,
password_changed_at: Some(TS.into()),
created_at: TS.into(),
created_by: Some(SUBJECT.into()),
updated_at: TS.into(),
updated_by: Some(SUBJECT.into()),
last_used_at: Some(TS.into()),
version: 3,
principal_did: None,
status: vti_common::vault::VaultStatus::Active,
archived_at: None,
deleted_at: None,
grace_until: None,
}
}
#[allow(deprecated)]
fn table() -> Vec<(&'static str, Conformance)> {
let mut t: Vec<(&'static str, Conformance)> = vec![
(
uris::TASK_TRUST_TASK_DISCOVERY_0_1,
checked!(
specs::trust_task_discovery::v0_1::Payload,
specs::trust_task_discovery::v0_1::Response,
json!({ "patterns": ["acl/*"] }),
json!({
"frameworkVersion": "0.2",
"supportedTypes": [
"https://trusttasks.org/spec/acl/grant/0.1",
"https://trusttasks.org/spec/acl/revoke/0.1"
]
})
),
),
(
uris::TASK_AUTH_REVOKE_SESSION_0_1,
checked!(
specs::auth::revoke_session::v0_1::Payload,
specs::auth::revoke_session::v0_1::Response,
to_v(RevokeSessionRequest {
all: None,
session_id: Some("sess-1".into()),
}),
to_v(RevokeSessionResponse { revoked_count: 1 })
),
),
(
uris::TASK_AUTH_WHOAMI_0_1,
checked!(
specs::auth::whoami::v0_1::Payload,
specs::auth::whoami::v0_1::Response,
json!({}), json!({ "session": session_json(), "roles": ["admin"], "scopes": ["ctx:root"] })
),
),
(
uris::TASK_AUTH_SESSIONS_LIST_0_1,
checked!(
specs::auth::sessions::list::v0_1::Payload,
specs::auth::sessions::list::v0_1::Response,
json!({}),
json!({ "sessions": [session_json()] })
),
),
(
uris::TASK_AUTH_STEP_UP_APPROVE_RESPONSE_0_1,
checked!(
specs::auth::step_up::approve_response::v0_1::Payload,
specs::auth::step_up::approve_response::v0_1::Response,
json!({
"subject": SUBJECT,
"sessionId": "sess-1",
"challenge": "chal-0123456789abcdef",
"decision": "approved",
"grantedAcr": "aal2",
"evidence": { "kind": "did-signed" },
}),
json!({ "status": "elevated", "session": session_json() })
),
),
(
uris::TASK_AUTH_STEP_UP_APPROVE_RESPONSE_0_2,
checked!(
specs::auth::step_up::approve_response::v0_2::Payload,
specs::auth::step_up::approve_response::v0_2::Response,
json!({
"subject": SUBJECT,
"sessionId": "sess-1",
"challenge": "chal-0123456789abcdef",
"decision": "approved",
"grantedAcr": "aal2",
"evidence": { "kind": "didSigned" },
}),
json!({ "status": "elevated", "session": session_json() })
),
),
(
uris::TASK_CONSENT_REQUEST_1_0,
checked!(
specs::consent::request::v1_0::Payload,
specs::consent::request::v1_0::Response,
to_v(ConsentRequestBody {
subject: consent_subject_json(),
scope: "converse".into(),
challenge: "chal-0123456789abcdef".into(),
display_hint: Some("Slack DM".into()),
first_message_digest: Some(DIGEST_MULTIBASE.into()),
context_hint: Some("ctx-a".into()),
}),
json!({ "status": "accepted", "requestId": "chal-1" })
),
),
(
uris::TASK_CONSENT_DECISION_1_0,
checked!(
specs::consent::decision::v1_0::Payload,
specs::consent::decision::v1_0::Response,
to_v(ConsentDecisionBody {
subject: consent_subject_json(),
effect: "allow".into(),
scope: Some("converse".into()),
challenge: Some("chal-0123456789abcdef".into()),
expires_at: None,
}),
json!({ "status": "recorded", "grantId": "urn:uuid:6d9c" })
),
),
(
uris::TASK_CONSENT_REVOKE_1_0,
checked!(
specs::consent::revoke::v1_0::Payload,
specs::consent::revoke::v1_0::Response,
to_v(ConsentRevokeBody {
subject: consent_subject_json(),
reason: None,
}),
json!({ "status": "revoked" })
),
),
(
uris::TASK_CONSENT_LIST_1_0,
checked!(
specs::consent::list::v1_0::Payload,
specs::consent::list::v1_0::Response,
to_v(ConsentListBody::default()),
json!({ "grants": [{
"subject": consent_subject_json(),
"effect": "allow",
"scope": "converse",
"grantedBy": "did:key:z6MkKeeper",
"grantedAt": TS,
"expiresAt": TS,
"evidence": "did-signed",
}] })
),
),
(
uris::TASK_CONSENT_APPROVER_SET_1_0,
checked!(
specs::consent::approver_set::v1_0::Payload,
specs::consent::approver_set::v1_0::Response,
to_v(ConsentApproverSetBody {
platform: "slack".into(),
context: "ctx-a".into(),
approver: "did:key:z6MkKeeper".into(),
route: Some("wake".into()),
route_hint: None,
}),
json!({ "status": "set" })
),
),
(
uris::TASK_CONSENT_APPROVER_LIST_1_0,
checked!(
specs::consent::approver_list::v1_0::Payload,
specs::consent::approver_list::v1_0::Response,
to_v(ConsentApproverListBody::default()),
json!({ "approvers": [{
"platform": "slack",
"context": "ctx-a",
"approver": "did:key:z6MkKeeper",
"route": "wake",
}] })
),
),
(
uris::TASK_TASK_CONSENT_DECISION_0_1,
checked!(
specs::task_consent::decision::v0_1::Payload,
specs::task_consent::decision::v0_1::Response,
json!({
"challenge": "chal-0123456789abcdef",
"payloadDigest": DIGEST_MULTIBASE,
"decision": "approve",
"reason": "looks right",
}),
json!({
"status": "pending",
"payloadDigest": DIGEST_MULTIBASE,
"approvals": 1,
"needed": 2,
})
),
),
(
uris::TASK_ACL_LIST_0_1,
checked!(
specs::acl::list::v0_1::Payload,
specs::acl::list::v0_1::Response,
to_v(ListAclBody {
role: Some("reader".into()),
scope: Some("ctx-a".into()),
direction: Some(ContextDirection::Subtree),
subject_prefix: Some("did:key:z6Mk".into()),
page_size: Some(50),
cursor: Some("cur-1".into()),
}),
to_v(ListAclResultBody {
entries: vec![acl_entry()],
truncated: false,
cursor: None,
redacted_fields: Vec::new(),
})
),
),
(
uris::TASK_ACL_GRANT_0_1,
checked!(
specs::acl::grant::v0_1::Payload,
specs::acl::grant::v0_1::Response,
to_v(CreateAclBody {
entry: acl_entry(),
reason: Some("onboarding".into()),
}),
to_v(CreateAclResponseBody { entry: acl_entry() })
),
),
(
uris::TASK_ACL_SHOW_0_1,
checked!(
specs::acl::show::v0_1::Payload,
specs::acl::show::v0_1::Response,
to_v(GetAclBody {
subject: SUBJECT.into(),
}),
to_v(GetAclResultBody {
entry: acl_entry(),
redacted_fields: Vec::new(),
})
),
),
(
uris::TASK_ACL_UPDATE_0_1,
checked!(
specs::acl::update::v0_1::Payload,
specs::acl::update::v0_1::Response,
to_v(UpdateAclBody {
did: SUBJECT.into(),
label: Some("renamed".into()),
allowed_contexts: Some(vec!["ctx-a".into(), "ctx-b".into()]),
expires_at: Some(dt()),
reason: Some("access review".into()),
step_up: Some(StepUp {
approver: Some("did:key:z6MkApprover".into()),
require: Some("delegated".into()),
}),
approve: Some(Approve {
all: false,
scopes: vec!["ctx-a".into()],
}),
allowed_keys: Some(Some(vec!["tenant-key-a".into()])),
}),
to_v(CreateAclResponseBody { entry: acl_entry() })
),
),
(
uris::TASK_ACL_CHANGE_ROLE_0_1,
checked!(
specs::acl::change_role::v0_1::Payload,
specs::acl::change_role::v0_1::Response,
to_v(ChangeRoleBody {
subject: SUBJECT.into(),
from_role: "reader".into(),
to_role: "application".into(),
reason: Some("promoted".into()),
}),
to_v(CreateAclResponseBody { entry: acl_entry() })
),
),
(
uris::TASK_ACL_REVOKE_0_1,
checked!(
specs::acl::revoke::v0_1::Payload,
specs::acl::revoke::v0_1::Response,
to_v(DeleteAclBody {
subject: SUBJECT.into(),
scopes: Some(vec!["ctx-a".into()]),
reason: Some("offboarding".into()),
}),
to_v(DeleteAclResultBody { entry: acl_entry() })
),
),
(
uris::TASK_ACL_SWAP_KEY_0_1,
checked!(
specs::acl::swap_key::v0_1::Payload,
specs::acl::swap_key::v0_1::Response,
to_v(SwapKeyBody {
current_subject: SUBJECT.into(),
new_subject: "did:key:z6MkNewSubject".into(),
link_proof: Some("eyJhbGciOiJFZERTQSJ9.e30.c2ln".into()),
reason: Some("wallet rotation".into()),
}),
to_v(SwapKeyResultBody {
entry: acl_entry(),
previous_subject: SUBJECT.into(),
})
),
),
(
uris::TASK_WEBVH_SERVERS_DOMAINS_0_1,
checked!(
specs::vta::webvh::servers::domains::v0_1::Payload,
specs::vta::webvh::servers::domains::v0_1::Response,
to_v(ListWebvhServerDomainsBody {
server_id: "primary-host".into(),
}),
to_v(ListWebvhServerDomainsResultBody {
domains: vec![WebvhServerDomainEntry {
name: "did.example.com".into(),
default_domain: true,
status: "active".into(),
label: Some("Production".into()),
created_at: Some("2026-03-01T00:00:00Z".into()),
}],
default: Some("did.example.com".into()),
})
),
),
(
uris::TASK_WEBVH_SERVERS_RECONCILE_0_1,
checked!(
specs::vta::webvh::servers::reconcile::v0_1::Payload,
specs::vta::webvh::servers::reconcile::v0_1::Response,
to_v(ReconcileWebvhServerDidsBody {
server_id: "primary-host".into(),
}),
to_v(ReconcileWebvhServerDidsResultBody {
server_id: "primary-host".into(),
host_only: vec![
HostOnlyDid {
slot_id: "attract-case".into(),
did: Some(
"did:webvh:QmZ4rT9xK2mN8vB5cD1sA7wE3fH6jL0pQ:did.example.com:attract-case"
.into(),
),
domain: Some("did.example.com".into()),
disabled: false,
},
HostOnlyDid {
slot_id: "quiet-harbour".into(),
did: None,
domain: None,
disabled: false,
},
],
agent_only: vec![AgentOnlyDid {
did: "did:webvh:QmY8nP3bV6xC1kM4hS9dF2gJ5tR7wL0zQ:did.example.com:never-landed"
.into(),
slot_id: "never-landed".into(),
context_id: "production".into(),
}],
in_both: 14,
})
),
),
(
uris::TASK_KEYS_LIST_0_1,
checked!(
specs::keys::list::v0_1::Payload,
specs::keys::list::v0_1::Response,
to_v(ListKeysBody {
offset: Some(0),
limit: Some(50),
status: Some(KeyStatus::Active),
context_id: Some("app".into()),
}),
to_v(ListKeysResultBody {
keys: vec![key_record()],
total: 1,
offset: 0,
limit: 50,
})
),
),
(
uris::TASK_KEYS_CREATE_0_1,
checked!(
specs::keys::create::v0_1::Payload,
specs::keys::create::v0_1::Response,
to_v(CreateKeyBody {
key_id: None,
internal: None,
key_type: KeyType::Ed25519,
derivation_path: Some("m/26'/2'/0'/1'".into()),
mnemonic: None,
label: Some("app signing key".into()),
context_id: Some("app".into()),
}),
to_v(CreateKeyResponseBody { key: key_result() })
),
),
(
uris::TASK_KEYS_IMPORT_0_1,
checked!(
specs::keys::import::v0_1::Payload,
specs::keys::import::v0_1::Response,
to_v(ImportKeyBody {
key_type: KeyType::Ed25519,
private_key_sealed: Some("-----BEGIN SEALED TRANSFER-----".into()),
private_key_jwe: None,
private_key_multibase: None,
label: Some("migrated signer".into()),
context_id: Some("app".into()),
}),
to_v(CreateKeyResponseBody { key: key_result() })
),
),
(
uris::TASK_KEYS_SHOW_0_1,
checked!(
specs::keys::show::v0_1::Payload,
specs::keys::show::v0_1::Response,
to_v(GetKeyBody {
key_id: "app-signing-key".into(),
}),
to_v(GetKeyResponseBody {
key: Some(key_record()),
})
),
),
(
uris::TASK_KEYS_RENAME_0_1,
checked!(
specs::keys::rename::v0_1::Payload,
specs::keys::rename::v0_1::Response,
to_v(RenameKeyBody {
key_id: "app-signing-key".into(),
new_key_id: "app-signing-key-2026".into(),
}),
to_v(RenameKeyResultBody {
key_id: "app-signing-key-2026".into(),
updated_at: dt(),
})
),
),
(
uris::TASK_KEYS_REVOKE_0_1,
checked!(
specs::keys::revoke::v0_1::Payload,
specs::keys::revoke::v0_1::Response,
to_v(RevokeKeyBody {
key_id: "app-signing-key".into(),
reason: Some("superseded".into()),
}),
to_v(RevokeKeyResultBody {
key_id: "app-signing-key".into(),
status: KeyStatus::Revoked,
updated_at: dt(),
})
),
),
(
uris::TASK_KEYS_SIGN_0_1,
checked!(
specs::keys::sign::v0_1::Payload,
specs::keys::sign::v0_1::Response,
to_v(SignRequestBody {
key_id: "app-signing-key".into(),
payload: "aGVsbG8".into(),
algorithm: SignAlgorithm::EdDSA,
}),
to_v(SignResultBody {
key_id: "app-signing-key".into(),
signature: "3q2-7w".into(),
algorithm: SignAlgorithm::EdDSA,
})
),
),
(
uris::TASK_KEYS_DERIVE_AND_SIGN_0_1,
checked!(
specs::keys::derive_and_sign::v0_1::Payload,
specs::keys::derive_and_sign::v0_1::Response,
to_v(DeriveAndSignBody {
key_type: KeyType::Ed25519,
derivation_path: "m/26'/9'/0'".into(),
payload: "aGVsbG8".into(),
algorithm: SignAlgorithm::EdDSA,
}),
to_v(DeriveAndSignResultBody {
public_key: "z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH".into(),
signature: "3q2-7w".into(),
algorithm: SignAlgorithm::EdDSA,
})
),
),
(
uris::TASK_KEYS_DERIVE_AND_SIGN_DOCUMENT_0_1,
checked!(
specs::keys::derive_and_sign_document::v0_1::Payload,
specs::keys::derive_and_sign_document::v0_1::Response,
to_v(DeriveAndSignDocumentBody {
key_type: KeyType::Ed25519,
derivation_path: "m/26'/9'/0'".into(),
document: json!({ "id": "urn:uuid:1", "payload": { "a": 1 } }),
proof_purpose: Some("assertionMethod".into()),
}),
to_v(DeriveAndSignDocumentResultBody {
signer_did: "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH".into(),
document: json!({ "id": "urn:uuid:1", "proof": { "type": "DataIntegrityProof" } }),
})
),
),
(
uris::TASK_DEVICE_REGISTER_0_1,
checked!(
specs::device::register::v0_1::Payload,
specs::device::register::v0_1::Response,
to_v(DeviceRegisterBody {
consumer_kind: json!({ "kind": "companion", "formFactor": "browser" }),
display_name: "Laptop".into(),
platform: None,
hpke_public_key: None,
}),
json!({ "binding": device_binding_json() })
),
),
(
uris::TASK_DEVICE_HEARTBEAT_0_1,
checked!(
specs::device::heartbeat::v0_1::Payload,
specs::device::heartbeat::v0_1::Response,
to_v(DeviceHeartbeatBody::default()),
json!({ "serverTime": TS, "queuedOperations": [], "syncHint": "up-to-date" })
),
),
(
uris::TASK_DEVICE_LIST_0_1,
checked!(
specs::device::list::v0_1::Payload,
specs::device::list::v0_1::Response,
json!({ "consumerKindFilter": "companion", "includeDisabled": true }),
json!({ "devices": [device_binding_json()], "truncated": false })
),
),
(
uris::TASK_DEVICE_DISABLE_0_1,
checked!(
specs::device::disable::v0_1::Payload,
specs::device::disable::v0_1::Response,
to_v(DeviceDisableBody {
device_id: "dev-1".into(),
reason: None,
}),
json!({ "deviceId": "dev-1", "disabledAt": TS })
),
),
(
uris::TASK_DEVICE_WIPE_0_1,
checked!(
specs::device::wipe::v0_1::Payload,
specs::device::wipe::v0_1::Response,
to_v(DeviceWipeBody {
device_id: "dev-1".into(),
scope: "full".into(),
reason: "stolen".into(),
}),
json!({ "deviceId": "dev-1", "scope": "full", "completedAt": TS })
),
),
(
uris::TASK_DEVICE_SET_WAKE_0_1,
checked!(
specs::device::set_wake::v0_1::Payload,
specs::device::set_wake::v0_1::Response,
to_v(DeviceSetWakeBody {
wake_handle: Some(WakeHandle {
gateway: "did:web:gateway.example".into(),
handle: "h-1".into(),
}),
suggested_triggers: Some(vec!["did:web:mediator.example".into()]),
}),
json!({
"pushCapable": true,
"triggerPolicy": { "allowedTriggers": ["did:web:mediator.example"] },
})
),
),
(
uris::TASK_MESSAGING_PING_0_1,
checked!(
specs::messaging::ping::v0_1::Payload,
specs::messaging::ping::v0_1::Response,
json!({ "nonce": "n-1" }),
json!({ "serverTime": TS, "status": "ok", "protocols": ["didcomm/v2"], "nonce": "n-1" })
),
),
(
uris::TASK_AUDIT_LIST_0_1,
checked!(
specs::audit::list::v0_1::Payload,
specs::audit::list::v0_1::Response,
to_v(ListAuditLogsBody {
from: Some(dt()),
to: Some(dt()),
action: Some("acl.update".into()),
actor: Some(SUBJECT.into()),
outcome: Some("success".into()),
context_id: Some("ctx-a".into()),
page_size: Some(100),
cursor: Some("cur-1".into()),
}),
to_v(ListAuditLogsResultBody {
entries: vec![AuditEnvelope {
event_id: "evt-1".into(),
recorded_at: TS.into(),
action: "acl.update".into(),
outcome: Some("success".into()),
actor: Some(SUBJECT.into()),
target: Some("did:key:z6MkTarget".into()),
context_id: Some("ctx-a".into()),
detail: serde_json::Map::new(),
}],
truncated: true,
cursor: Some("cur-2".into()),
})
),
),
(
credx::PENDING_LIST,
checked!(
specs::credential_exchange::pending::list::v0_1::Payload,
specs::credential_exchange::pending::list::v0_1::Response,
json!({}),
to_v(PendingListResponse {
pending: vec![PendingPresentationSummary {
id: "thr-1".into(),
verifier_did: "did:web:verifier.example".into(),
requested: vec![RequestedCredentialSummary {
credential_query_id: "q-1".into(),
credential_id: "cred-1".into(),
claims: vec!["givenName".into()],
}],
purpose: "age verification".into(),
created_at: dt(),
expires_at: dt(),
}],
})
),
),
(
credx::PENDING_APPROVE,
checked!(
specs::credential_exchange::pending::approve::v0_1::Payload,
specs::credential_exchange::pending::approve::v0_1::Response,
to_v(PendingApproveBody { id: "thr-1".into() }),
to_v(PresentBody {
vp_token: json!({ "vp": {} }),
})
),
),
(
credx::PENDING_DENY,
checked!(
specs::credential_exchange::pending::deny::v0_1::Payload,
specs::credential_exchange::pending::deny::v0_1::Response,
to_v(PendingDenyBody { id: "thr-1".into() }),
to_v(PendingDenyResponse {
id: "thr-1".into(),
status: "denied".into(),
})
),
),
(
uris::TASK_VAULT_LIST_0_1,
checked!(
specs::vault::list::v0_1::Payload,
specs::vault::list::v0_1::Response,
json!({
"contextId": "ctx-a",
"targetOriginPrefix": "https://example.com",
"secretKind": "password",
"tag": "work",
"status": "active",
"pageSize": 20,
}),
json!({ "entries": [to_v(vault_entry())], "truncated": false })
),
),
(
uris::TASK_VAULT_GET_0_1,
checked!(
specs::vault::get::v0_1::Payload,
specs::vault::get::v0_1::Response,
json!({ "id": "01HVAULTENTRY" }),
json!({ "entry": to_v(vault_entry()) })
),
),
(
uris::TASK_VAULT_UPSERT_0_1,
checked!(
specs::vault::upsert::v0_1::Payload,
specs::vault::upsert::v0_1::Response,
{
let mut v = to_v(VaultUpsertBody {
context_id: "ctx-a".into(),
targets: vec![
json!({ "kind": "web-origin", "origin": "https://example.com" }),
],
label: "example.com login".into(),
secret_kind: "password".into(),
id: None,
expected_version: None,
tags: None,
notes: None,
expires_at: None,
extra: serde_json::Map::new(),
});
v.as_object_mut().expect("body is an object").insert(
"sealedSecret".into(),
json!({ "envelope": "didcomm-authcrypt", "jwe": "eyJ0eXAiOiJKV0UifQ" }),
);
v
},
json!({ "entry": to_v(vault_entry()), "created": false })
),
),
(
uris::TASK_VAULT_DELETE_0_1,
checked!(
specs::vault::delete::v0_1::Payload,
specs::vault::delete::v0_1::Response,
to_v(vta_sdk::protocols::vault_management::VaultDeleteBody {
id: "01HVAULTENTRY".into(),
force: false,
expected_version: None,
reason: None,
}),
json!({ "id": "01HVAULTENTRY", "deletedAt": TS, "graceUntil": TS })
),
),
(
uris::TASK_VAULT_RELEASE_0_1,
checked!(
specs::vault::release::v0_1::Payload,
specs::vault::release::v0_1::Response,
json!({
"entryId": "01HVAULTENTRY",
"target": { "kind": "web-origin", "origin": "https://example.com" },
"consumerContext": { "deviceId": "dev-1", "networkClass": "home" },
"ttlSecondsHint": 60,
}),
json!({
"sealedSecret": { "envelope": "didcomm-authcrypt", "jwe": "eyJwcm90ZWN0ZWQiOiJ..." },
"secretKind": "password",
"ttlSeconds": 60,
})
),
),
(
uris::TASK_VAULT_PROXY_LOGIN_0_1,
checked!(
specs::vault::proxy_login::v0_1::Payload,
specs::vault::proxy_login::v0_1::Response,
json!({
"entryId": "01HVAULTENTRY",
"target": { "kind": "web-origin", "origin": "https://example.com" },
"nonce": "n-1",
"ttlSecondsHint": 60,
}),
json!({
"sealedSessionBlob": { "envelope": "didcomm-authcrypt", "jwe": "eyJwcm90ZWN0ZWQiOiJ..." },
"ext": { "org.openvtc.vault-session": { "sessionId": "vs-1", "expiresAt": TS } },
})
),
),
(
uris::TASK_VAULT_SIGN_TRUST_TASK_0_1,
checked!(
specs::vault::sign_trust_task::v0_1::Payload,
specs::vault::sign_trust_task::v0_1::Response,
json!({
"entryId": "01HVAULTENTRY",
"unsignedEnvelope": {
"id": "urn:uuid:7c11",
"type": "https://trusttasks.org/spec/messaging/ping/0.1",
"issuer": SUBJECT,
"recipient": "did:web:vta.example",
"issuedAt": TS,
"payload": { "nonce": "n-1" },
},
}),
json!({ "signedEnvelope": {
"id": "urn:uuid:7c11",
"type": "https://trusttasks.org/spec/messaging/ping/0.1",
"issuer": SUBJECT,
"recipient": "did:web:vta.example",
"issuedAt": TS,
"payload": { "nonce": "n-1" },
"proof": { "type": "DataIntegrityProof" },
} })
),
),
(
uris::TASK_VTA_CREDENTIALS_ISSUE_0_2,
checked!(
specs::vta::credentials::issue::v0_2::Payload,
specs::vta::credentials::issue::v0_2::Response,
to_v(IssueCredentialBody {
holder: SUBJECT.into(),
claims: json!({ "role": "agent" }),
credential_type: Some("AgentAuthorization".into()),
validity_seconds: 3600,
purpose: Some("agent onboarding".into()),
authorization_context: None,
}),
to_v(IssueCredentialResponse {
credential_id: "cred-1".into(),
credential: json!({ "@context": [], "type": ["VerifiableCredential"] }),
expires_at: TS.into(),
issued_at: Some(TS.into()),
})
),
),
(
uris::TASK_VTA_CREDENTIALS_REVOKE_0_1,
checked!(
specs::vta::credentials::revoke::v0_1::Payload,
specs::vta::credentials::revoke::v0_1::Response,
to_v(RevokeCredentialBody {
credential_id: "cred-1".into(),
reason: Some("holder offboarded".into()),
}),
to_v(RevokeCredentialResponse {
credential_id: "cred-1".into(),
revoked_at: TS.into(),
})
),
),
(
uris::TASK_VTA_MEMORY_PUT_0_1,
checked!(
specs::vta::memory::put::v0_1::Payload,
specs::vta::memory::put::v0_1::Response,
to_v(MemoryPutBody {
context_id: "ctx-a".into(),
key: "greeting".into(),
value: "hello".into(),
}),
to_v(MemoryPutResponse {
key: "greeting".into(),
})
),
),
(
uris::TASK_VTA_MEMORY_LIST_0_1,
checked!(
specs::vta::memory::list::v0_1::Payload,
specs::vta::memory::list::v0_1::Response,
to_v(MemoryListBody {
context_id: "ctx-a".into(),
}),
to_v(MemoryListResponse {
items: vec![MemoryItem {
key: "greeting".into(),
value: "hello".into(),
}],
})
),
),
(
uris::TASK_VTA_MEMORY_DELETE_0_1,
checked!(
specs::vta::memory::delete::v0_1::Payload,
specs::vta::memory::delete::v0_1::Response,
to_v(MemoryDeleteBody {
context_id: "ctx-a".into(),
key: "greeting".into(),
}),
to_v(MemoryDeleteResponse {
key: "greeting".into(),
})
),
),
(
uris::TASK_VTA_APP_STATE_GET_1_0,
checked!(
specs::vta::app_state::get::v1_0::Payload,
specs::vta::app_state::get::v1_0::Response,
to_v(AppStateGetBody {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/acme".into(),
include_deleted: None,
ext: None,
}),
to_v(AppStateGetResponse {
record: app_state_record(),
})
),
),
(
uris::TASK_VTA_APP_STATE_PUT_1_0,
checked!(
specs::vta::app_state::put::v1_0::Payload,
specs::vta::app_state::put::v1_0::Response,
to_v(AppStatePutBody {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/acme".into(),
value: Some(serde_json::json!({ "label": "Acme" })),
merge_patch: None,
expected_version: Some(47),
ext: None,
}),
to_v(AppStatePutResponse {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/acme".into(),
version: 52,
created: false,
updated_at: TS.into(),
value_bytes: Some(95),
})
),
),
(
uris::TASK_VTA_APP_STATE_LIST_1_0,
checked!(
specs::vta::app_state::list::v1_0::Payload,
specs::vta::app_state::list::v1_0::Response,
to_v(AppStateListBody {
context_id: "ctx-a".into(),
namespace: Some("openvtc".into()),
prefix: Some("community/".into()),
since_version: Some(40),
include_values: Some(true),
include_deleted: None,
page_size: Some(50),
cursor: None,
ext: None,
}),
to_v(AppStateListResponse {
records: vec![app_state_record(), app_state_tombstone()],
truncated: false,
cursor: None,
high_watermark: Some(52),
tombstone_retention_seconds: Some(2_592_000),
})
),
),
(
uris::TASK_VTA_APP_STATE_DELETE_1_0,
checked!(
specs::vta::app_state::delete::v1_0::Payload,
specs::vta::app_state::delete::v1_0::Response,
to_v(AppStateDeleteBody {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/defunct".into(),
expected_version: Some(44),
ext: None,
}),
to_v(AppStateDeleteResponse {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
key: "community/defunct".into(),
existed: true,
version: Some(54),
deleted_at: Some(TS.into()),
})
),
),
(
uris::TASK_VTA_APP_STATE_GET_MANY_1_0,
checked!(
specs::vta::app_state::get_many::v1_0::Payload,
specs::vta::app_state::get_many::v1_0::Response,
to_v(AppStateGetManyBody {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
keys: vec!["community/acme".into(), "profile/labels".into()],
include_deleted: None,
ext: None,
}),
to_v(AppStateGetManyResponse {
records: vec![app_state_record()],
missing: vec!["profile/labels".into()],
deferred: None,
})
),
),
(
uris::TASK_VTA_APP_STATE_PUT_MANY_1_0,
checked!(
specs::vta::app_state::put_many::v1_0::Payload,
specs::vta::app_state::put_many::v1_0::Response,
to_v(AppStatePutManyBody {
context_id: "ctx-a".into(),
namespace: "openvtc".into(),
mode: Some(PutManyMode::Independent),
writes: vec![
AppStateWrite {
key: "community/acme".into(),
value: None,
merge_patch: Some(serde_json::json!({ "role": "owner" })),
expected_version: Some(52),
},
AppStateWrite {
key: "profile/labels".into(),
value: Some(serde_json::json!({ "colours": { "acme": "blue" } })),
merge_patch: None,
expected_version: Some(0),
},
],
ext: None,
}),
to_v(AppStatePutManyResponse {
mode: PutManyMode::Independent,
results: vec![
WriteResult {
key: "community/acme".into(),
outcome: WriteOutcome::Written,
version: Some(59),
created: Some(false),
current_version: None,
current_value: None,
current_deleted: None,
limit_bytes: None,
actual_bytes: None,
},
WriteResult {
key: "profile/labels".into(),
outcome: WriteOutcome::Conflict,
version: None,
created: None,
current_version: Some(57),
current_value: Some(serde_json::json!({ "colours": {} })),
current_deleted: None,
limit_bytes: None,
actual_bytes: None,
},
],
high_watermark: Some(60),
})
),
),
(
uris::TASK_POLICY_LIST_0_2,
checked!(
specs::policy::list::v0_2::Payload,
specs::policy::list::v0_2::Response,
to_v(ListPoliciesBody {
context_id: Some("ctx-a".into()),
enabled_only: true,
cursor: None,
page_size: Some(50),
}),
to_v(ListPoliciesResultBody {
policies: vec![policy_module_view()],
truncated: false,
cursor: None,
})
),
),
(
uris::TASK_POLICY_GET_0_1,
checked!(
specs::policy::get::v0_1::Payload,
specs::policy::get::v0_1::Response,
to_v(GetPolicyBody {
id: "approvals".into(),
}),
to_v(GetPolicyResultBody {
policy: policy_module_view(),
})
),
),
(
uris::TASK_POLICY_UPSERT_0_2,
checked!(
specs::policy::upsert::v0_2::Payload,
specs::policy::upsert::v0_2::Response,
to_v(UpsertPolicyBody {
id: Some("approvals".into()),
name: "Declarative approvals".into(),
description: None,
module: declarative_module(),
applies_to: vec![],
priority: Some(vta_sdk::approvals::DECLARATIVE_POLICY_PRIORITY),
enabled: true,
expected_version: Some(1),
ext: declarative_ext(),
}),
to_v(UpsertPolicyResultBody {
policy: policy_module_view(),
created: false,
})
),
),
(
uris::TASK_POLICY_DELETE_0_1,
checked!(
specs::policy::delete::v0_1::Payload,
specs::policy::delete::v0_1::Response,
to_v(DeletePolicyBody {
id: "legacy-rego".into(),
expected_version: Some(2),
reason: Some("superseded by the declarative rules".into()),
}),
to_v(DeletePolicyResultBody {
id: "legacy-rego".into(),
deleted_at: TS.into(),
})
),
),
(
uris::TASK_CONFIG_SHOW_0_1,
checked!(
specs::config::show::v0_1::Payload,
specs::config::show::v0_1::Response,
to_v(GetConfigBody {
keys: Some(vec!["public_url".into()]),
}),
to_v(GetConfigResultBody {
fields: vec![ConfigField {
key: "public_url".into(),
value: json!("https://vta.example"),
source: "db".into(),
requires_restart: false,
}],
})
),
),
(
uris::TASK_CONFIG_PATCH_0_1,
checked!(
specs::config::patch::v0_1::Payload,
specs::config::patch::v0_1::Response,
to_v(UpdateConfigBody {
overrides: [("public_url".to_string(), json!("https://vta.example"))]
.into_iter()
.collect(),
}),
to_v(UpdateConfigResultBody {
applied: vec!["public_url".into()],
pending_restart: vec![],
rejected: vec![RejectedKey {
key: "vta_did".into(),
reason: "immutable".into(),
}],
})
),
),
];
{
use vta_sdk::did_templates::{DidTemplate, DidTemplateRecord, Scope};
use vta_sdk::protocols::did_template_management as tpl;
const TPL_NAME: &str = "didcomm-mediator";
const CTX: &str = "ctx-a";
const EPOCH: u64 = 1_785_369_600;
fn template() -> DidTemplate {
DidTemplate {
schema_version: 1,
name: TPL_NAME.into(),
kind: "mediator".into(),
description: Some("DIDComm mediator".into()),
methods: vec!["webvh".into()],
required_vars: vec!["SERVICE_ENDPOINT".into()],
optional_vars: [("LABEL".to_string(), json!("mediator"))]
.into_iter()
.collect(),
defaults: [("preRotationCount".to_string(), json!(2))]
.into_iter()
.collect(),
document: json!({
"id": "{DID}",
"service": [{
"id": "{DID}#didcomm",
"type": "DIDCommMessaging",
"serviceEndpoint": "{SERVICE_ENDPOINT}",
}],
}),
}
}
fn record() -> DidTemplateRecord {
DidTemplateRecord {
template: template(),
scope: Scope::Context {
context_id: CTX.into(),
},
created_at: EPOCH,
updated_at: EPOCH,
created_by: "did:key:z6MkAdmin".into(),
}
}
fn rendered() -> Value {
json!({
"id": "did:webvh:scid:vta.example",
"service": [{
"id": "did:webvh:scid:vta.example#didcomm",
"type": "DIDCommMessaging",
"serviceEndpoint": "https://mediator.example",
}],
})
}
for (what, parse, global) in [
(
"list",
parses::<specs::vta::did_templates::list::v2_0::Payload> as ParseFn,
to_v(tpl::list::ListDidTemplatesBody { context_id: None }),
),
(
"create",
parses::<specs::vta::did_templates::create::v2_0::Payload> as ParseFn,
to_v(tpl::create::CreateDidTemplateBody {
context_id: None,
template: template(),
}),
),
(
"get",
parses::<specs::vta::did_templates::get::v2_0::Payload> as ParseFn,
to_v(tpl::get::GetDidTemplateBody {
context_id: None,
name: TPL_NAME.into(),
}),
),
(
"update",
parses::<specs::vta::did_templates::update::v2_0::Payload> as ParseFn,
to_v(tpl::update::UpdateDidTemplateBody {
context_id: None,
name: TPL_NAME.into(),
template: template(),
}),
),
(
"delete",
parses::<specs::vta::did_templates::delete::v2_0::Payload> as ParseFn,
to_v(tpl::delete::DeleteDidTemplateBody {
context_id: None,
name: TPL_NAME.into(),
}),
),
(
"render",
parses::<specs::vta::did_templates::render::v2_0::Payload> as ParseFn,
to_v(tpl::render::RenderDidTemplateBody {
context_id: None,
name: TPL_NAME.into(),
vars: HashMap::new(),
}),
),
] {
assert!(
global.get("contextId").is_none(),
"did-templates/{what}: the global fixture must omit contextId"
);
parse(global.clone()).unwrap_or_else(|e| {
panic!(
"did-templates/{what}: global-scope request is not canonical: {e}\n{global:#}"
)
});
}
t.extend([
(
uris::TASK_DID_TEMPLATES_LIST_2_0,
checked!(
specs::vta::did_templates::list::v2_0::Payload,
specs::vta::did_templates::list::v2_0::Response,
to_v(tpl::list::ListDidTemplatesBody {
context_id: Some(CTX.into()),
}),
to_v(tpl::list::ListDidTemplatesResultBody {
templates: vec![record()],
})
),
),
(
uris::TASK_DID_TEMPLATES_CREATE_2_0,
checked!(
specs::vta::did_templates::create::v2_0::Payload,
specs::vta::did_templates::create::v2_0::Response,
to_v(tpl::create::CreateDidTemplateBody {
context_id: Some(CTX.into()),
template: template(),
}),
to_v(record())
),
),
(
uris::TASK_DID_TEMPLATES_GET_2_0,
checked!(
specs::vta::did_templates::get::v2_0::Payload,
specs::vta::did_templates::get::v2_0::Response,
to_v(tpl::get::GetDidTemplateBody {
context_id: Some(CTX.into()),
name: TPL_NAME.into(),
}),
to_v(record())
),
),
(
uris::TASK_DID_TEMPLATES_UPDATE_2_0,
checked!(
specs::vta::did_templates::update::v2_0::Payload,
specs::vta::did_templates::update::v2_0::Response,
to_v(tpl::update::UpdateDidTemplateBody {
context_id: Some(CTX.into()),
name: TPL_NAME.into(),
template: template(),
}),
to_v(record())
),
),
(
uris::TASK_DID_TEMPLATES_DELETE_2_0,
checked!(
specs::vta::did_templates::delete::v2_0::Payload,
specs::vta::did_templates::delete::v2_0::Response,
to_v(tpl::delete::DeleteDidTemplateBody {
context_id: Some(CTX.into()),
name: TPL_NAME.into(),
}),
to_v(tpl::delete::DeleteDidTemplateResultBody {
name: TPL_NAME.into(),
deleted: true,
})
),
),
(
uris::TASK_DID_TEMPLATES_RENDER_2_0,
checked!(
specs::vta::did_templates::render::v2_0::Payload,
specs::vta::did_templates::render::v2_0::Response,
to_v(tpl::render::RenderDidTemplateBody {
context_id: Some(CTX.into()),
name: TPL_NAME.into(),
vars: [(
"SERVICE_ENDPOINT".to_string(),
json!("https://mediator.example")
)]
.into_iter()
.collect(),
}),
to_v(tpl::render::RenderDidTemplateResultBody {
document: rendered(),
})
),
),
]);
}
#[cfg(all(feature = "webvh", feature = "didcomm"))]
{
use vta_sdk::protocols::did_management::passkey_vms as pk;
fn vm() -> pk::PasskeyVerificationMethod {
pk::PasskeyVerificationMethod {
id: "did:webvh:scid:vta.example#passkey-1".into(),
vm_type: "Multikey".into(),
controller: "did:webvh:scid:vta.example".into(),
public_key_multibase: "z6MkPasskey".into(),
webauthn_credential_id: "b64u-cred-id".into(),
webauthn_transports: vec!["internal".into()],
label: Some("YubiKey".into()),
}
}
t.extend([
(
uris::TASK_PASSKEY_VMS_ENROLL_CHALLENGE_0_1,
checked!(
specs::vta::passkey_vms::enroll_challenge::v0_1::Payload,
specs::vta::passkey_vms::enroll_challenge::v0_1::Response,
to_v(pk::EnrollPasskeyChallengeBody {
did: "did:webvh:scid:vta.example".into(),
label: Some("YubiKey".into()),
}),
to_v(pk::EnrollPasskeyChallengeResponse {
ceremony_id: "cer-1".into(),
challenge: "b64u-challenge".into(),
rp_id: "vta.example".into(),
rp_name: "VTA".into(),
user_handle: "b64u-handle".into(),
user_name: "operator".into(),
user_display_name: "Operator".into(),
timeout_ms: Some(60_000),
})
),
),
(
uris::TASK_PASSKEY_VMS_ENROLL_SUBMIT_0_1,
checked!(
specs::vta::passkey_vms::enroll_submit::v0_1::Payload,
specs::vta::passkey_vms::enroll_submit::v0_1::Response,
to_v(pk::EnrollPasskeySubmitBody {
did: "did:webvh:scid:vta.example".into(),
ceremony_id: "cer-1".into(),
credential_id: "b64u-cred-id".into(),
public_key_multibase: "z6MkPasskey".into(),
cose_algorithm: -8,
attestation_object: "b64u-atto".into(),
client_data_json: "b64u-cdj".into(),
authenticator_data: "b64u-authdata".into(),
transports: vec!["internal".into()],
label: Some("YubiKey".into()),
}),
to_v(pk::EnrollPasskeySubmitResponse {
verification_method: vm(),
webvh_version: "2-zVer".into(),
})
),
),
(
uris::TASK_PASSKEY_VMS_LIST_0_1,
checked!(
specs::vta::passkey_vms::list::v0_1::Payload,
specs::vta::passkey_vms::list::v0_1::Response,
to_v(pk::ListPasskeyVmsBody {
did: "did:webvh:scid:vta.example".into(),
}),
to_v(pk::ListPasskeyVmsResponse {
verification_methods: vec![vm()],
})
),
),
(
uris::TASK_PASSKEY_VMS_REVOKE_0_1,
checked!(
specs::vta::passkey_vms::revoke::v0_1::Payload,
specs::vta::passkey_vms::revoke::v0_1::Response,
to_v(pk::RevokePasskeyVmBody {
did: "did:webvh:scid:vta.example".into(),
fragment: "passkey-1".into(),
}),
to_v(pk::RevokePasskeyVmResponse::default())
),
),
]);
}
#[cfg(feature = "webvh")]
{
use vta_sdk::provision_integration::http as prov;
let request = json!({
"request": {
"@context": ["https://www.w3.org/ns/credentials/v2",
"https://openvtc.org/contexts/bootstrap-v1"],
"type": ["VerifiablePresentation", "BootstrapRequest"],
"id": "urn:uuid:9be7",
"holder": "did:key:z6MkAgentSetup",
"nonce": "AAAAAAAAAAAAAAAAAAAAAA",
"validUntil": TS,
"ask": { "type": "templateBootstrap", "template": { "name": "didcomm-mediator" } },
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"created": TS,
"verificationMethod": "did:key:z6MkAgentSetup#z6MkAgentSetup",
"proofPurpose": "authentication",
"proofValue": "z5TvSig",
},
},
"context": "agents",
"assertion": "didSigned",
"vcValiditySeconds": 3600,
"createContext": true,
});
let response = to_v(prov::ProvisionIntegrationResponse {
bundle: "-----BEGIN VTA SEALED BUNDLE-----".into(),
digest_multibase: Some(DIGEST_MULTIBASE.into()),
summary: prov::ProvisionSummary {
client_did: "did:key:z6MkAgentSetup".into(),
admin_did: "did:key:z6MkAdmin".into(),
admin_rolled_over: true,
integration_did: Some("did:webvh:scid:agents.example".into()),
template_name: Some("didcomm-mediator".into()),
template_kind: Some("mediator".into()),
admin_template_name: Some("vta-admin".into()),
bundle_id_hex: "0123456789abcdef0123456789abcdef".into(),
secret_count: 2,
output_count: 1,
webvh_server_id: Some("srv-1".into()),
context_created: true,
},
});
serde_json::from_value::<prov::ProvisionIntegrationRequest>(request.clone())
.expect("canonical provision request parses into ProvisionIntegrationRequest");
t.push((
uris::TASK_PROVISION_INTEGRATION_0_3,
checked!(
specs::provision::integration::v0_3::Payload,
specs::provision::integration::v0_3::Response,
request,
response
),
));
}
#[cfg(feature = "webvh")]
{
use vta_sdk::protocols::did_management::update::{
UpdateDidWebvhBody, UpdateDidWebvhResultBody,
};
t.push((
uris::TASK_WEBVH_DIDS_UPDATE_1_0,
checked!(
specs::vta::webvh::dids::update::v1_0::Payload,
specs::vta::webvh::dids::update::v1_0::Response,
vta_sdk::client::flatten_with_did(
"did:webvh:scid:vta.example",
&UpdateDidWebvhBody {
label: Some("rotate after audit".into()),
..Default::default()
},
)
.expect("the producer's own shaping succeeds"),
to_v(UpdateDidWebvhResultBody {
did: "did:webvh:scid:vta.example".into(),
new_version_id: "2-zVer".into(),
new_scid: "scid".into(),
new_log_entry: "{}".into(),
update_keys_count: 1,
pre_rotation_key_count: 2,
serverless: false,
})
),
));
}
for (uri, req, resp) in webvh_and_context_witnesses() {
t.push((
uri,
Conformance::Checked(Witness {
request: req.0,
parse_request: req.1,
validate_request: req.2,
response: resp.0,
parse_response: resp.1,
}),
));
}
t
}
type ReqParts = (Value, ParseFn, ValidateFn);
type RespParts = (Value, ParseFn);
fn webvh_and_context_witnesses() -> Vec<(&'static str, ReqParts, RespParts)> {
use specs::vta::{contexts as ctx, services as svc, webvh as wv};
let context_record = || {
json!({
"id": "personal", "name": "Personal", "basePath": "personal",
"createdAt": "2026-08-19T09:00:00Z", "updatedAt": "2026-08-19T09:00:00Z"
})
};
let did_record = || {
json!({
"did": "did:webvh:QmScid:host.example:alice", "serverId": "prod",
"mnemonic": "alice", "scid": "QmScid", "contextId": "personal",
"portable": true, "logEntryCount": 4,
"createdAt": "2026-08-19T09:00:00Z", "updatedAt": "2026-08-19T09:00:00Z"
})
};
let server_record = || {
json!({
"id": "prod", "did": "did:web:host.example",
"createdAt": "2026-08-19T09:00:00Z", "updatedAt": "2026-08-19T09:00:00Z"
})
};
let did = "did:webvh:QmScid:host.example:alice";
let mutation_result = || {
json!({
"logEntryVersionId": "4-zQmLogEntry",
"effectiveAt": "2026-08-20T09:00:00Z",
"vtaDid": "did:webvh:QmAgent:vta.example",
"serverless": false
})
};
let mut v: Vec<(&'static str, ReqParts, RespParts)> = vec![
(
uris::TASK_CONTEXTS_LIST_1_0,
(
json!({}),
parses::<ctx::list::v1_0::Payload>,
validates::<ctx::list::v1_0::Payload>,
),
(
json!({ "contexts": [context_record()] }),
parses::<ctx::list::v1_0::Response>,
),
),
(
uris::TASK_CONTEXTS_GET_1_0,
(
json!({ "id": "personal" }),
parses::<ctx::get::v1_0::Payload>,
validates::<ctx::get::v1_0::Payload>,
),
(context_record(), parses::<ctx::get::v1_0::Response>),
),
(
uris::TASK_CONTEXTS_CREATE_1_0,
(
json!({ "id": "personal", "name": "Personal" }),
parses::<ctx::create::v1_0::Payload>,
validates::<ctx::create::v1_0::Payload>,
),
(context_record(), parses::<ctx::create::v1_0::Response>),
),
(
uris::TASK_CONTEXTS_UPDATE_1_0,
(
json!({ "id": "personal" }),
parses::<ctx::update::v1_0::Payload>,
validates::<ctx::update::v1_0::Payload>,
),
(context_record(), parses::<ctx::update::v1_0::Response>),
),
(
uris::TASK_CONTEXTS_UPDATE_DID_1_0,
(
json!({ "id": "personal", "did": did }),
parses::<ctx::update_did::v1_0::Payload>,
validates::<ctx::update_did::v1_0::Payload>,
),
(context_record(), parses::<ctx::update_did::v1_0::Response>),
),
(
uris::TASK_CONTEXTS_PREVIEW_DELETE_1_0,
(
json!({ "id": "personal" }),
parses::<ctx::preview_delete::v1_0::Payload>,
validates::<ctx::preview_delete::v1_0::Payload>,
),
(
json!({ "id": "personal", "keys": ["k-1"], "webvhDids": [],
"aclEntriesRemoved": ["did:key:zRemoved"], "aclEntriesUpdated": [] }),
parses::<ctx::preview_delete::v1_0::Response>,
),
),
(
uris::TASK_CONTEXTS_DELETE_1_0,
(
json!({ "id": "personal" }),
parses::<ctx::delete::v1_0::Payload>,
validates::<ctx::delete::v1_0::Payload>,
),
(
json!({ "id": "personal", "deleted": true }),
parses::<ctx::delete::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_LIST_1_0,
(
json!({}),
parses::<wv::dids::list::v1_0::Payload>,
validates::<wv::dids::list::v1_0::Payload>,
),
(
json!({ "dids": [did_record()] }),
parses::<wv::dids::list::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_GET_1_0,
(
json!({ "did": did }),
parses::<wv::dids::get::v1_0::Payload>,
validates::<wv::dids::get::v1_0::Payload>,
),
(
json!({ "record": did_record() }),
parses::<wv::dids::get::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_CREATE_1_0,
(
json!({ "contextId": "personal" }),
parses::<wv::dids::create::v1_0::Payload>,
validates::<wv::dids::create::v1_0::Payload>,
),
(
json!({ "did": did, "contextId": "personal", "scid": "QmScid", "portable": true,
"signingKeyId": "k-sign", "kaKeyId": "k-ka", "preRotationKeyCount": 2,
"createdAt": "2026-08-19T09:00:00Z" }),
parses::<wv::dids::create::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_DELETE_1_0,
(
json!({ "did": did }),
parses::<wv::dids::delete::v1_0::Payload>,
validates::<wv::dids::delete::v1_0::Payload>,
),
(
json!({ "did": did, "deleted": true }),
parses::<wv::dids::delete::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_ROTATE_KEYS_1_0,
(
json!({ "did": did }),
parses::<wv::dids::rotate_keys::v1_0::Payload>,
validates::<wv::dids::rotate_keys::v1_0::Payload>,
),
(
json!({ "did": did, "newVersionId": "2-zVer", "newScid": "QmScid", "newLogEntry": "{}",
"updateKeysCount": 1, "preRotationKeyCount": 2, "serverless": false }),
parses::<wv::dids::rotate_keys::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_DIDS_REGISTER_WITH_SERVER_1_0,
(
json!({ "did": did, "serverId": "prod" }),
parses::<wv::dids::register_with_server::v1_0::Payload>,
validates::<wv::dids::register_with_server::v1_0::Payload>,
),
(
json!({ "did": did, "serverId": "prod", "logEntryCount": 4 }),
parses::<wv::dids::register_with_server::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_SERVERS_LIST_1_0,
(
json!({}),
parses::<wv::servers::list::v1_0::Payload>,
validates::<wv::servers::list::v1_0::Payload>,
),
(
json!({ "servers": [server_record()] }),
parses::<wv::servers::list::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_SERVERS_REGISTER_1_0,
(
json!({ "id": "prod" }),
parses::<wv::servers::register::v1_0::Payload>,
validates::<wv::servers::register::v1_0::Payload>,
),
(
server_record(),
parses::<wv::servers::register::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_SERVERS_RETIRE_ORPHAN_0_1,
(
to_v(RetireOrphanSlotBody {
server_id: "primary-host".into(),
slot_id: "attract-case".into(),
expected_did: Some(
"did:webvh:QmZ4rT9xK2mN8vB5cD1sA7wE3fH6jL0pQ:did.example.com:attract-case"
.into(),
),
reason: Some("orphaned by a create whose reply was lost".into()),
}),
parses::<wv::servers::retire_orphan::v0_1::Payload>,
validates::<wv::servers::retire_orphan::v0_1::Payload>,
),
(
to_v(RetireOrphanSlotResultBody {
server_id: "primary-host".into(),
slot_id: "attract-case".into(),
retired: true,
did: Some(
"did:webvh:QmZ4rT9xK2mN8vB5cD1sA7wE3fH6jL0pQ:did.example.com:attract-case"
.into(),
),
}),
parses::<wv::servers::retire_orphan::v0_1::Response>,
),
),
(
uris::TASK_WEBVH_SERVERS_REMOVE_1_0,
(
json!({ "id": "prod" }),
parses::<wv::servers::remove::v1_0::Payload>,
validates::<wv::servers::remove::v1_0::Payload>,
),
(
json!({ "id": "prod", "removed": true }),
parses::<wv::servers::remove::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_SET_1_0,
(
json!({ "did": did, "name": "alice" }),
parses::<wv::agent_name::set::v1_0::Payload>,
validates::<wv::agent_name::set::v1_0::Payload>,
),
(
json!({ "did": did, "name": "alice", "enabled": true }),
parses::<wv::agent_name::set::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_REMOVE_1_0,
(
json!({ "did": did, "name": "alice" }),
parses::<wv::agent_name::remove::v1_0::Payload>,
validates::<wv::agent_name::remove::v1_0::Payload>,
),
(
json!({ "did": did, "name": "alice", "enabled": false }),
parses::<wv::agent_name::remove::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_LIST_1_0,
(
json!({ "did": did }),
parses::<wv::agent_name::list::v1_0::Payload>,
validates::<wv::agent_name::list::v1_0::Payload>,
),
(
json!({ "did": did, "names": [{ "name": "alice", "enabled": true }] }),
parses::<wv::agent_name::list::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_CHECK_1_0,
(
json!({ "did": did, "name": "alice" }),
parses::<wv::agent_name::check::v1_0::Payload>,
validates::<wv::agent_name::check::v1_0::Payload>,
),
(
json!({ "name": "alice", "domain": "host.example", "available": true, "reserved": false }),
parses::<wv::agent_name::check::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_ENABLE_1_0,
(
json!({ "did": did, "name": "alice" }),
parses::<wv::agent_name::enable::v1_0::Payload>,
validates::<wv::agent_name::enable::v1_0::Payload>,
),
(
json!({ "did": did, "name": "alice", "enabled": true }),
parses::<wv::agent_name::enable::v1_0::Response>,
),
),
(
uris::TASK_WEBVH_AGENT_NAME_DISABLE_1_0,
(
json!({ "did": did, "name": "alice" }),
parses::<wv::agent_name::disable::v1_0::Payload>,
validates::<wv::agent_name::disable::v1_0::Payload>,
),
(
json!({ "did": did, "name": "alice", "enabled": false }),
parses::<wv::agent_name::disable::v1_0::Response>,
),
),
];
#[cfg(feature = "webvh")]
{
let services: [(&'static str, ReqParts, RespParts); 8] = [
(
uris::TASK_SERVICES_LIST_1_0,
(
json!({}),
parses::<svc::list::v1_0::Payload>,
validates::<svc::list::v1_0::Payload>,
),
(
json!({ "services": [{ "kind": "rest", "enabled": true, "url": "https://vta.example/api" }] }),
parses::<svc::list::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_GET_1_0,
(
json!({ "service": "didcomm" }),
parses::<svc::get::v1_0::Payload>,
validates::<svc::get::v1_0::Payload>,
),
(
json!({ "state": { "kind": "didcomm", "enabled": true, "mediatorDid": "did:web:mediator.example" } }),
parses::<svc::get::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_ENABLE_1_0,
(
json!({ "service": "rest", "config": { "url": "https://vta.example/api" } }),
parses::<svc::enable::v1_0::Payload>,
validates::<svc::enable::v1_0::Payload>,
),
(
json!({ "result": mutation_result() }),
parses::<svc::enable::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_UPDATE_1_0,
(
json!({ "service": "tsp", "config": { "mediatorDid": "did:web:mediator.example" } }),
parses::<svc::update::v1_0::Payload>,
validates::<svc::update::v1_0::Payload>,
),
(
json!({ "result": mutation_result() }),
parses::<svc::update::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_DISABLE_1_0,
(
json!({ "service": "didcomm" }),
parses::<svc::disable::v1_0::Payload>,
validates::<svc::disable::v1_0::Payload>,
),
(
json!({ "result": mutation_result() }),
parses::<svc::disable::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_ROLLBACK_1_0,
(
json!({ "service": "rest" }),
parses::<svc::rollback::v1_0::Payload>,
validates::<svc::rollback::v1_0::Payload>,
),
(
json!({ "result": { "kind": "noOp", "serverless": false } }),
parses::<svc::rollback::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_DRAIN_LIST_1_0,
(
json!({}),
parses::<svc::drain::list::v1_0::Payload>,
validates::<svc::drain::list::v1_0::Payload>,
),
(
json!({ "entries": [{ "mediatorDid": "did:web:old-mediator.example",
"endpoint": "https://old-mediator.example/didcomm",
"drainsUntil": "2026-08-20T21:00:00Z" }] }),
parses::<svc::drain::list::v1_0::Response>,
),
),
(
uris::TASK_SERVICES_DRAIN_CANCEL_1_0,
(
json!({ "mediatorDid": "did:web:old-mediator.example" }),
parses::<svc::drain::cancel::v1_0::Payload>,
validates::<svc::drain::cancel::v1_0::Payload>,
),
(
json!({ "mediatorDid": "did:web:old-mediator.example" }),
parses::<svc::drain::cancel::v1_0::Response>,
),
),
];
v.extend(services);
}
v
}
#[test]
fn every_published_dispatched_uri_has_a_witness() {
let expected = resolved_uris();
let mut covered = BTreeSet::new();
for (uri, _) in table() {
assert!(
covered.insert(uri),
"duplicate witness entry for {uri} — one entry per URI"
);
}
let missing: Vec<_> = expected.difference(&covered).collect();
assert!(
missing.is_empty(),
"these dispatched URIs are published in the registry but have no \
conformance witness:\n {}\n\nAdd a `checked!` entry (request + \
response built from the slice's wire types), or — only for a real, \
understood non-conformance — a `KnownDrift` entry with a reason. If \
this fired after a rebase, a sibling consolidation stream rebound a \
task onto a published URI; the sweep is asking for its witness.",
missing
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join("\n ")
);
let stale: Vec<_> = covered.difference(&expected).collect();
assert!(
stale.is_empty(),
"these witnesses cover URIs that are no longer both dispatched and \
published:\n {}\n\nRemove them (or fix the constant they name).",
stale
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join("\n ")
);
}
#[test]
fn every_witnessed_task_round_trips_through_its_generated_types() {
let mut drift: Vec<String> = Vec::new();
for (uri, conformance) in table() {
let w = match conformance {
Conformance::Checked(w) => w,
Conformance::KnownDrift(reason) => {
assert!(
!reason.trim().is_empty(),
"{uri}: KnownDrift entries must state the drift"
);
drift.push(format!("{uri}: {reason}"));
continue;
}
};
(w.parse_request)(w.request.clone())
.unwrap_or_else(|e| panic!("{uri}: request is not canonical: {e}\n{:#}", w.request));
(w.parse_response)(w.response.clone())
.unwrap_or_else(|e| panic!("{uri}: response is not canonical: {e}\n{:#}", w.response));
(w.validate_request)(&w.request).unwrap_or_else(|e| {
panic!(
"{uri}: request fails its own payload schema: {e}\n{:#}",
w.request
)
});
for (side, value, parse) in [
("request", &w.request, w.parse_request),
("response", &w.response, w.parse_response),
] {
let mut drifted = value.clone();
drifted
.as_object_mut()
.unwrap_or_else(|| panic!("{uri}: {side} witness must be a JSON object"))
.insert("__conformance_sweep_drift".into(), json!(true));
assert!(
parse(drifted).is_err(),
"{uri}: the generated {side} type accepted an unknown member — \
this witness can pass vacuously and proves nothing"
);
}
}
for line in &drift {
eprintln!("KNOWN DRIFT (follow-up issue required): {line}");
}
}