1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Context methods on [`VtaClient`].
use super::{
ContextListResponse, ContextResponse, CreateContextRequest, UpdateContextRequest, VtaClient,
};
use crate::error::VtaError;
#[cfg(feature = "client")]
use crate::protocols::context_management;
#[cfg(feature = "client")]
impl VtaClient {
pub async fn list_contexts(&self) -> Result<ContextListResponse, VtaError> {
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_LIST_1_0,
serde_json::json!({}),
30,
)
.await
}
pub async fn get_context(&self, id: &str) -> Result<ContextResponse, VtaError> {
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_GET_1_0,
serde_json::json!({ "id": id }),
30,
)
.await
}
pub async fn create_context(
&self,
req: CreateContextRequest,
) -> Result<ContextResponse, VtaError> {
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_CREATE_1_0,
serde_json::to_value(&req)?,
30,
)
.await
}
pub async fn update_context(
&self,
id: &str,
req: UpdateContextRequest,
) -> Result<ContextResponse, VtaError> {
// Built from the request struct rather than a `json!` literal, for two
// reasons the literal got wrong.
//
// It named the members by hand and omitted `contextPolicy`, so a caller
// setting a policy had it silently dropped — the field was accepted and
// never sent. And it read `req.name`/`req.did`/`req.description`
// directly, which bypasses their `skip_serializing_if` and emits
// `null` for every unset one; the agent rejects that as
// `malformedRequest`, since an absent optional must be ABSENT.
let mut payload = serde_json::to_value(&req)?;
match payload.as_object_mut() {
Some(obj) => {
obj.insert("id".into(), serde_json::Value::String(id.to_string()));
}
None => {
return Err(VtaError::Protocol(
"update-context request did not serialize to an object".into(),
));
}
}
self.rpc_tt(crate::trust_tasks::TASK_CONTEXTS_UPDATE_1_0, payload, 30)
.await
}
/// Update the DID for a context. Requires Admin role with access to the context.
pub async fn update_context_did(
&self,
id: &str,
did: impl Into<String>,
) -> Result<ContextResponse, VtaError> {
let did = did.into();
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_UPDATE_DID_1_0,
serde_json::json!({ "id": id, "did": &did }),
30,
)
.await
}
pub async fn preview_delete_context(
&self,
id: &str,
) -> Result<context_management::delete::DeleteContextPreviewResultBody, VtaError> {
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_PREVIEW_DELETE_1_0,
serde_json::json!({ "id": id }),
30,
)
.await
}
/// Delete a context, discarding the response.
///
/// Prefer
/// [`delete_context_with_outcome`](Self::delete_context_with_outcome):
/// a successful `vta/contexts/delete/1.0` can still carry
/// `daemonCleanupErrors`, which the specification says a consumer MUST
/// surface, and this method cannot. Same shape, and the same reason, as
/// [`delete_did_webvh`](Self::delete_did_webvh).
pub async fn delete_context(&self, id: &str, force: bool) -> Result<(), VtaError> {
self.rpc_tt_void(
crate::trust_tasks::TASK_CONTEXTS_DELETE_1_0,
serde_json::json!({ "id": id, "force": force }),
30,
)
.await
}
/// Delete a context and return the `vta/contexts/delete/1.0` response.
///
/// A success carrying `daemon_cleanup_errors` is a partial success: the
/// contexts and their records are gone, but for the named `did:webvh`
/// DIDs the hosting server did not confirm removing the published log, so
/// **they may still resolve**. The specification requires a consumer to
/// surface that rather than report the deletion as complete.
///
/// `deleted: false` on a success means the VTA declined to act; read the
/// member rather than the transport status.
pub async fn delete_context_with_outcome(
&self,
id: &str,
force: bool,
) -> Result<trust_tasks_rs::specs::vta::contexts::delete::v1_0::Response, VtaError> {
self.rpc_tt(
crate::trust_tasks::TASK_CONTEXTS_DELETE_1_0,
serde_json::json!({ "id": id, "force": force }),
30,
)
.await
}
}