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
//! Bootstrap / provision-integration methods on [`VtaClient`].
use super::{Transport, VtaClient};
use crate::error::VtaError;
impl VtaClient {
/// Bridge a VP-framed bootstrap request to the VTA and receive
/// the sealed bundle.
///
/// Works over both transports:
/// - **REST**: `POST /bootstrap/provision-integration`.
/// - **DIDComm**: `provision-integration/1.0` protocol over the
/// open authcrypt session. The VTA-side handler is the same
/// shared library function as REST; only the I/O differs.
///
/// In DIDComm mode, the session's `client_did` must already
/// hold admin role in the target context's ACL. Sender and VP
/// holder may legitimately differ — the air-gap onboarding flow
/// relies on this, since the bundle is HPKE-sealed to the VP
/// holder's X25519 derivation and the relayer can't decrypt it.
#[cfg(feature = "provision-integration")]
pub async fn provision_integration(
&self,
req: crate::provision_integration::http::ProvisionIntegrationRequest,
) -> Result<crate::provision_integration::http::ProvisionIntegrationResponse, VtaError> {
match &self.transport {
Transport::Rest {
client,
base_url,
auth,
} => {
Self::ensure_token_valid(client, base_url, auth).await?;
let token = auth.lock().await.token.clone();
let http_req = client
.post(format!("{base_url}/bootstrap/provision-integration"))
.json(&req);
let resp = Self::with_auth_token(http_req, &token).send().await?;
Self::handle_response(resp).await
}
#[cfg(feature = "session")]
Transport::DIDComm { session, .. } => {
crate::provision_integration::didcomm::provision_integration_didcomm(
session,
req.request,
req.context,
req.assertion,
req.vc_validity_seconds,
req.create_context,
)
.await
}
}
}
}