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
//! DIDComm transport for `provision-integration`.
//!
//! Holder side. Sends a VP-framed [`super::BootstrapRequest`] over an
//! authcrypt'd DIDComm session and receives the sealed
//! `TemplateBootstrap` bundle in the reply. Wire shapes are
//! transport-neutral — the payload that arrives is the same armored
//! bundle the REST endpoint returns.
//!
//! Use this when the holder already has a DIDComm session open to the
//! VTA (e.g., the integration's setup wizard). For file-based offline
//! bootstrap, use the `vta bootstrap provision-integration` CLI on the
//! VTA host.
//!
//! Auth model — layered like an onion. The DIDComm authcrypt
//! sender authenticates the *relayer* and is gated by the VTA's
//! ACL (sender must be admin in the target context). Inside the
//! body, the VP's `DataIntegrityProof` authenticates the *holder*
//! — the bundle is HPKE-sealed to the holder's X25519 derivation,
//! so only the holder can open it. Sender and holder may legitimately
//! differ; the air-gap onboarding flow relies on this:
//!
//! 1. Third-party integration (air-gapped) signs a BootstrapRequest
//! with its own ephemeral did:key.
//! 2. Request is transferred to the operator's host.
//! 3. Operator's PNM relays the request over its DIDComm session.
//! 4. VTA issues the bundle, sealed to the integration.
//! 5. Operator carries the (encrypted) bundle back across the
//! air-gap; only the integration can decrypt.
use crateDIDCommSession;
use crateVtaError;
use crate;
use BootstrapRequest;
use ;
/// Default DIDComm round-trip timeout (seconds). Generous so the VTA
/// has time to mint keys, render templates, build the webvh log, and
/// seal the bundle — all of which happen synchronously inside the
/// shared library function before the reply lands.
const DEFAULT_TIMEOUT_SECS: u64 = 60;
/// Send a `provision-integration` request over an existing DIDComm
/// session.
///
/// The holder must have an authcrypt'd DIDComm session open to the
/// VTA — see [`DIDCommSession::connect`]. The session's `client_did`
/// must already hold admin role in the target context's ACL; the VTA
/// rejects with `Forbidden` (mapped to [`VtaError::Auth`]) otherwise.
///
/// Returns the same shape the REST endpoint produces: armored sealed
/// bundle + sha256 digest + summary (including `admin_did` /
/// `admin_rolled_over` when the VP requested rollover via
/// `adminTemplate`).
///
/// `assertion` defaults to [`AssertionMode::DidSigned`] when `None`.
///
/// `create_context` opts into super-admin context creation when the
/// target context isn't yet registered — same semantics as the REST
/// path. Default is `false` (caller must have created the context
/// out-of-band).
///
/// `context` is `Option<String>`. Pass `Some(name)` for the
/// integration-class pattern (caller knows which bucket to provision
/// into); pass `None` to let the VTA infer per the canonical Trust
/// Task spec's three rules — typical for wallet-class callers that
/// don't track the maintainer's context layout. See
/// [`crate::provision_integration::http::ProvisionIntegrationRequest::context`]
/// for the full inference rules + error semantics.
///
/// `spec_version` selects the Trust Task wire version. [`ProvisionSpecVersion::V0_1`]
/// emits the legacy snake_case option fields + kebab `assertion` under the
/// `provision/integration/0.1` URI; [`ProvisionSpecVersion::V0_2`] emits
/// lowerCamelCase (`vcValiditySeconds` / `createContext` / `didSigned`) under
/// the `0.2` URI. The signed VP carried in `request` is left byte-identical
/// either way — its casing is the holder's, and the VTA dual-accepts both.
pub async