libVES.js
Overview
VESvault: Simple, Safe and Secure Encryption At-rest
The structure of end-to-end encrypted VES Repository is described in the VES Repository Documentation.
The latest source code can be found at the GitHub repository.
Usage
The latest stable version of libVES can be included or downloaded from https://ves.host/pub/libVES.js.
libVES can be used with any existing VES account.
An interactive browser-based integration should start with either flow() or delegate(), called on a libVES instance with a domain provided, to unlock the User's vault, and to walk the User through VES setup process if necessary. The following calls are intended for most common integrations:
  • putValue(): Store an e2ee value in VES repo, optionally e2ee share with other users
  • getValue(): Retrieve an e2ee value stored by the User or shared with the User
  • shareFile(): Share a previously stored value, or other type of Vault Item, with specified Users
  • deleteFile(): Delete a previously stored value, or other type of Vault Item, from VES repo
  • fileExists(): Check if a value, or other type of Vault Item, is stored in VES repo
  • externalId property identifies the authenticated App Vault
  • me(): Get the identity of the authenticated VES User
See JSfiddle for a sample integration using delegate() authentication. Note that flow() cannot run on JSfiddle because of frame policies.
See demo.ves.world for a VES authentication demo.
new libVES(options)
Create a new instance of libVES.
options object libVES constructor options domain String App Domain Tag. Required to access a Secondary Vault externalId String External ID. Required for non-interactive access to a Secondary Vault apiUrl String VESvault REST API base URL. Defaults to the official endpoint, https://api.ves.host/v1/. keyAlgo String Default algorithm tag for newly created Vault Keys. Defaults to ECDH. user String VESvault account user name (email address). Required to access a Primary Vault
libVES A new instance of libVES
object libVES.Error Inconsistent parameters
VES = new libVES({"user": "me@domain.com"});
VES = new libVES({"domain": "myApp", "externalId": "me@domain.com"});
delegate(optns)
Log in and unlock a secondary vault using a VESvault popup window, see Demo.
optns Object or null All keys are optional. email String VES account email hint. item String ExternalID of a VaultItem to get access to. Affects the VES account selection, and forces a Viewer Vault authentication. rd String Optional redundancy alert option. Set to app for non-intrusive flow.
Promise(libVES) When the promise is resolved, the instance of libVES is unlocked with a respective secondary Vault Key. The reference to the libVES instance is also returned as the value of the promise.
libVES.Error Delegate login failed or aborted
new libVES({domain: 'myDomain'}).delegate().then(function(VES) {
    VES.me().then(function(me) {
	VES.getVaultKey().then(function(key) {
	    Promise.all([me.getId(),me.getEmail(),key.getId()]).then(function(data) {
		console.log("Logged in as User " + data[0] + " (" + data[1] + "), vault key " + data[2]);
	    });
	});
    });
}).catch(function(error) {
    window.alert(error);
});
flow(start, optns)
Log in and unlock a secondary vault via interactive VES Flow process in the same window, see Demo
start boolean true: force start the authentication flow, redirect to VESvault authorization page unless authentication exchange data from VESvault is present in the page URL.
false: passive mode, accept authentication exchange data from VESvault if present in the page URL, throw an expection otherwise.
optns object See delegate()
Promise(libVES) When the promise is resolved, the instance of libVES is unlocked with a respective secondary Vault Key. The reference to the libVES instance is also returned as the value of the promise.
libVES.Error.Redirect Redirecting the current window to vesvault.com
libVES.Error VES Flow failed or aborted
new libVES({domain: 'myDomain'}).flow(true).then(function(VES) {
    VES.me().then(function(me) {
	VES.getVaultKey().then(function(key) {
	    Promise.all([me.getId(),me.getEmail(),key.getId()]).then(function(data) {
		console.log("Logged in as User " + data[0] + " (" + data[1] + "), vault key " + data[2]);
	    });
	});
    });
}).catch(function(error) {
    if (error instanceof libVES.Error.Redirect) return;
    window.alert(error);
});
getValue(fileRef)
Decrypt the value stored in the Vault, identified by the file reference.
fileRef Object File Reference
Promise(…) The decrypted value, formatted according to the type
libVES.Error No such file? No access to the file? Vault is not unlocked?
VES.getValue({"domain":"myDomain","externalId":"myItem1"}).then(function(value) {
    console.log('Value: ' + value);
}).catch(function(error) {
    window.alert(error);
});
putValue(fileRef,value,shareWith)
Deposit the value in the Vault. Create the File entry and associated entries if doesn't exist.
fileRef Object File Reference
value The value to be deposited, formatted according to the type. For existing Vault Item the type of the value must match the type of the item. For a new Vault Item, the type of the Vault Item is autodetected based on the type of the value.
shareWith Array(…) List of Vault References to share with. Optional. For a new item, defaults to the owner's secondary vault within the item file's domain.
Promise(libVES.VaultItem) Vault Item if successful
libVES.Error Incorrect value type? No permission for this file?
VES.putValue({"domain":"myDomain","externalId":"myItem1"},"secret content").then(function(vaultItem) {
    vaultItem.getId().then(function(id) {
	console.log('Vault Item ID: ' + id);
    });
}).catch(function(error) {
    window.alert(error);
});
shareFile(fileRef,shareWith)
Share an existing VESvault file item with other Vault Keys.
fileRef Object File Reference
shareWith Array(…) List of Vault References to share with.
Promise(libVES.VaultItem) Vault Item if successful
libVES.Error File does not exist? No permission for this file? The list of vault references doesn't include the Owner's Vault Key?
VES.shareFile({"domain":"myDomain","externalId":"myItem1"},[{"domain":"myDomain","externalId":"user1"},{"domain":"myDomain","externalId":"user2"}]).then(function(vaultItem) {
    vaultItem.getId().then(function(id) {
	console.log('Vault Item ID: ' + id);
    });
}).catch(function(error) {
    window.alert(error);
});
deleteFile(fileRef)
Delete a file entry, and any associated items.
fileRef Object File Reference
Promise(true) Deleted
libVES.Error No such file? No access to the file?
VES.deleteFile({"domain":"myDomain","externalId":"myItem1"}).then(function() {
    console.log('deleted');
}).catch(function(error) {
    window.alert(error);
});
fileExists(fileRef)
Check if a file exists in VESvault
fileRef Object File Reference
Promise(boolean) True or false
libVES.Error Internal error?
VES.fileExists({"domain":"myDomain","externalId":"myItem1"}).then(function(result) {
    console.log(result);
}).catch(function(error) {
    window.alert(error);
});
me()
The owner of the Primary or Secondary Vault
Promise(libVES.User) The owner of the Vault
libVES.Error Error (not authenticated?)
VES.me().then(function(me) {
    Promise.all([me.getId(),me.getEmail()]).then(function(data) {
	console.log("I am User " + data[0] + " (" + data[1] + ")");
    });
}).catch(function(error) {
    window.alert(error);
});
login(password)
Log in to a primary VESvault account. For VESvault internal use. Applies to the username supplied in the constructor options.
Not applicable to Secondary Vault
password String or Promise One-time password generated by VESvault
Promise(libVES.User) Logged in user
libVES.Error Login failed
VES.login("myPassword").then(function(me) {
    Promise.all([me.getId(),me.getEmail()]).then(function(data) {
	console.log("Logged in as User " + data[0] + " (" + data[1] + ")");
    });
}).catch(function(error) {
    window.alert(error);
});
logout()
Log out of the VESvault account, if logged in. Also locks the Vault if it was unlocked.
(Promise) true Always succeeds
VES.logout();
getVaultKey()
Current Vault Key for a Primary Vault, null if not set up. Secondary Vault Key for a Secondary Vault.
Promise(libVES.VaultKey) The active Vault Key
libVES.Error Error (not authenticated?)
VES.getVaultKey().then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
unlock(veskey)
Unlock the Vault Key. Need to be logged in to VESvault account to unlock the Primary Vault. If the vault is already unlocked, a call without the veskey argument will return the unlocked CryptoKey
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
veskey String or Promise VESkey (Vault Key Passphrase)
Promise(CryptoKey) Unlocked CryptoKey
libVES.Error Unlock failed (incorrect VESkey?)
VES.unlock("veskey").then(function(cryptoKey) {
    console.log("VESvault key is unlocked...",cryptoKey);
}).catch(function(error) {
    window.alert(error);
});
lock()
Lock the Vault, if unlocked
Promise(true) Always succeeds
VES.lock();
setVESkey(veskey,lost,options)
Rekey the Vault. Create a new Vault Key with the supplied VESkey as a passphrase.
veskey String or Promise New VESkey
lost boolean Set to true to flag the Current Vault Key as lost, and initiate VESrecovery. Applicable to Primary Vault only.
options object Vault Key Options. Optional.
Promise(libVES.VaultKey) The new Vault Key
libVES.Error Rekey failed
VES.setVESkey("myVESkey",false).then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
setShadow(friends,options)
Create, replace or remove a Shadow Vault Key, to be used for VESrecovery in case of losing the VESkey. Applicable only to Primary Vault. The Vault must be unlocked prior to this call.
friends Array(…) Array of Vault References. Primary Vaults only. Pass an empty array to remove the Shadow and disable VESrecovery.
options Object Recovery options. v String Recovery algorithm version. Defaults to RDX1.2 n Int Number of Friends needed to assist in VESrecovery. Required.
Promise(libVES.VaultKey) The new Shadow Vault Key, or null if removed
libVES.Error Shadow setup failed
VES.setShadow(["friend1@domain.com","friend2@domain.com","friend3@domain.com"],{"a":"RDX1.2", "n":2}).then(function(vaultKey) {
    Promise.all([vaultKey.getId(),vaultKey.getType(),vaultKey.getAlgo()]).then(function(data) {
	console.log("Vault Key #" + data[0] + " type = " + data[1] + ", algo = " + data[2]);
    });
}).catch(function(error) {
    window.alert(error);
});
getMyRecoveries()
Get info and status of the current VESrecoveries for the User's lost Vault Keys.
Promise(Array(libVES.Recovery)) User's Own Recoveries
libVES.Error Failed.
VES.getMyRecoveries().then(function(recoveries) {
    for (var i = 0; i < recoveries.length; i++)	console.log(recoveries[i]);
}).catch(function(error) {
    window.alert(error);
});
getFriendsRecoveries()
Access the Friends' VESrecoveries the User might be able to assist at.
Promise(Array(libVES.Recovery)) Friends' VESrecoveries
libVES.Error Failed.
VES.getMyRecoveries().then(function(recoveries) {
    for (var i = 0; i < recoveries.length; i++)	console.log(recoveries[i]);
}).catch(function(error) {
    window.alert(error);
});
libVES.User
Object libVES.User represents a VESvault user account. An interface to REST API call users.
getId()
Promise(Int) VESvault User ID.
getEmail()
Promise(String) User email address.
getFirstName()
Promise(String) User's first name.
getLastName()
Promise(String) User's last name.
getFullName()
Promise(String) User's full name, assembled from the first and last name.
getVaultKeys()
Promise(Array(libVES.VaultKey)) All User's Vault Keys
getCurrentVaultKey()
Promise(libVES.VaultKey) User's current primary Vault Key. null if not set.
libVES.VaultKey
Object libVES.VaultKey represents an asymmetric Vault Key. An interface to REST API call vaultKeys.
Vault Key Types
The following types of Vault Key are supported in VESvault:
current The current Primary Vault Key. The passphrase for the current key is the user's primary VESkey. Only one current key may exist per VESvault account at any moment. When the user sets a new primary VESkey, all the vault entries from the old current Vault Key are rekeyed, and the old current Vault Key is deleted. If the user has lost the VESkey, the current Vault Key changes the type to lost, and the new current key is created for the new VESkey.
temp A temporary Vault Key, created on the behalf of another VESvault user. A temporary key always has a Creator - a VESvault user who created the key. If a temp key has External reference, it is intended to be rekeyed to a Secondary key with same External. A temp key with no External is intended to be rekeyed to the Primary (current) Vault Key. Multiple temp keys may exist per VESvault account, with diferrent Creators and/or Externals. When Alice shares a Vault Item with Bob, and Bob doesn't have a VESvault account, or doesn't have a proper Vault Key set up, Alice creates a temp Vault Key. The owner of the created key is Bob, the creator is Alice. The External reference of the created key is empty if Alice shares with Bob's Primary Vault, or is set accordingly (domain & externalId) if Alice shares with Bob's Secondary Vault. The passphrase for the temp key is a randomly generated string. Alice stores the generated passphrase as a Vault Item in her vault. If Bob already had a current (Primary) Vault Key, and Alice has generated a temp key for a Bob's secondary vault, Alice shares the passphrase Vault Item with Bob's Primary Vault. Otherwise, Alice remains the sole holder of Bob's temp passphrase until Bob sets up his Primary Vault. When Alice unlocks her Vault and detects that Bob has set up his Primary Vault (key type current), Alice shares the temp passphrase with Bob's Primary Vault. Next time Bob unlocks his Primary Vault, the system (libVES or VESvault web interface) creates the missing Secondary Vault Keys, and rekeys all items from the temp keys, using the temp passphrases shared with his Primary Vault. Once done, Bob deletes the temp keys.
secondary A secondary Vault Key. Isentified by the owner and the External reference. The passphrase is called the Secondary VESkey, and is stored as a Vault Item in the owner's Primary Vault. Multiple Secondary keys with different Externals may exist in a User's VESvault. If the user loses the Secondary VESkey, he will need to unlock the Primary Vault to retrieve the stored Secondary VESkey. If the Primary VESkey is also lost, VESrecovery is needed to regain access to the Primary Vault.
lost When a VESvault user loses the Primary VESkey, he creates a new VESkey, and the type of the old current VESkey is changed to lost. At this point, VESrecovery is initiated (if it was set up). Once the recovery is achieved, or the user finds his lost VESkey, all the vault entries are rekeyed from the lost key to the new current key, and the lost key is deleted.
shadow Shadow key allows the user to gain access to encrypted data through VESrecovery process, in case of losing the Primary VESkey. The passphrase to the Shadow key is a randomly generated string, and is referred to as Recovery Secret. When the Shadow key is being created, the Recovery Secret is passed through the Scramble Algorithm that produces multiple Recovery Tokens. The Recovery Secret can be reconstructed from a predefined number of Recovery Tokens. Each Recovery Token is stored as a Vault Item and is shared with a specific friend. All the Vault Items deposited in the user's Primary Vault are reflected on the Shadow Key. When the user indicates the loss of the Primary VESkey, the status of the Shadow Key is changed to recovery, and a new blank Shadow Key with same set of friends is created. Only one Shadow key can exist per VESvault account can exist at a given time.
recovery When the user indicates the loss of the Primary VESkey, the status of the Shadow Key is changed from shadow to recovery. Each friend is prompted to assist – share his Recovery Token back with the User's new Primary Vault. Once the required number of friends have assisted, the VESrecovery is achieved. The Vault Key can be unlocked now, all the items can be rekeyed to the current Primary Vault, and the old key is deleted.
pending Type pending is reserved for background operations in the future implementations. Pending keys are not returned by getVaultKeys(), and can be accessed only by ID. After 7 days, pending key is considered abandoned and may be automatically permanently deleted along with any associated entries.
deleted Type deleted is a proposed experimental safety measure against permanent loss of data in case of incorrect rekeying. Deleted keys are not returned by getVaultKeys(), and can be accessed only by ID. After 30 days, deleted key is considered abandoned and may be automatically permanently deleted along with any associated entries.
Vault References
Vault Reference is a convenient way to identify Vault Keys to deposit or share an item with. Vault References are used by sharing functions, such as vaultItem.shareWith() and VES.setShadow().
A Vault Reference may be any of the following:
  • Primary Vault Reference:
    • (String) A properly formatted user's email address. The VESvault user with the specified email will be automatically created if it doesn't exist yet.
    • (object) A user hint object. Either id or email is required: id VESvault User ID. If set, matches a user, throws an error if none matched. email User email address. If set, matches a user, creates a new user if none matched. firstName First name hint. Updated for the matched or created VESvault User is wasn't set before, ignored otherwise. lastName Last name hint. Updated for the matched or created VESvault User is wasn't set before, ignored otherwise.
    • (libVES.User) A VESvault user object
  • Secondary Vault Reference:
    • (object) A Secondary Vault hint object. Both domain and externalId are required: domain App domain tag. externalId External ID. Unique within the app domain. user User hint, optional. May be of any type described in the Primary Vault Reference.
      • If the Secondary Vault Key is matched by external reference (domain & externalId) – the user hint is ignored.
      • Else, if the app domain specific validation is passed, and the user hint matches or creates a valid user – the External reference is created.
      • Otherwise – throws an error.
    • (libVES.VaultKey) A Vault Key, type secondary
    • (libVES.External) An External reference, pointing to a Vault Key type secondary
getId()
Promise(Int) Vault Key ID.
getUser()
Promise(libVES.User) The Vault Key owner.
getType()
Promise(String) Vault Key Type.
getAlgo()
Promise(String) Asymmetric Algorithm tag.
getPublicKey()
Promise(String) The public key, PKCS#1 PEM formatted string.
getPrivateKey()
Promise(String) The encrypted private key, PKCS#5 PEM formatted string.
getVaultEntries()
Promise(Array(object)) The vault entries encrypted with the Vault Key. vaultItem object id = VaultItem ID encData String Base64 encoded encrypted VaultItem data
getExternals()
Promise(Array(libVES.External)) The external references. In the current version, no more than 1 external reference is supported per VaultKey. Applicable to type external or temp.
getCreator()
Promise(libVES.User) The key creator. Applicable to type temp.
getVaultItems()
Promise(Array(libVES.VaultItem)) Supplementary Vault Items. Applicable to type temp (passphrase), or shadow/recovery (recovery tokens).
getRecovery()
Promise(libVES.Recovery) The VESrecovery control object. Applicable to type shadow/recovery.
unlock(veskey)
Unlock the Vault Key. If the Vault Key is already unlocked, a call without the veskey argument will return the unlocked CryptoKey
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
veskey String or Promise Passphrase
Promise(CryptoKey) Unlocked CryptoKey
libVES.Error Unlock failed (incorrect passphrase?)
lock()
Lock the Vault Key, if unlocked
Promise(true) Always succeeds
getPublicCryptoKey()
Load the Public Key as a CryptoKey object.
If the platform's Web Crypto API lacks support for the key algo, the returned value may be of a custom type different than CryptoKey, but of similar sense
Promise(CryptoKey) Public Key as a CryptoKey
libVES.Error Inalid public key?
getUnlockedPrivateKey()
Get the unencrypted PEM private key. The Vault Key must be unlocked to decrypt the private key.
Promise(String) The unencrypted private key, PKCS#8 PEM formatted.
libVES.Error Vault Key is not unlocked?
encrypt(plainText)
Encrypt raw data. A low level call, use vaultItem.shareWith() for high level.
plainText Uint8Array or ArrayBuffer Raw binary plaintext to encrypt
Promise(String) Base64 encoded ciphertext.
libVES.Error Bad public key?
decrypt(cipherText)
Decrypt raw data. A low level call, use vaultItem.get() for high level.
cipherText String Base64 encoded ciphertext.
Promise(Uint8Array) Raw binary plaintext.
libVES.Error Vault Key is not unlocked?
libVES.VaultItem
Object libVES.VaultItem represents an item stored in VESvault. The Vault Item may be shared with one or more Primary or Secondary Vaults, restriction rules apply based on type. Arbitrary metadata can be stored along with an item. The length of serialized metadata should nexer exceed 65536 bytes. To avoid potential interference with future extensions, use 'x_' prefix on the custom metadata keys.
An interface to REST API call vaultItems.
Vault Item Types
The following types of Vault Items are currently implemented in VESvault:
password A relatively short secret phrase. Might be either an arbitrary password stored in a lockbox, or a stored passphrase to a particular Vault Key, type secondary or temp. The parsed content of the Vault Item is a String.
string An arbitrary secret text, stored in a lockbox. The binary version of the ciphertext should never exceed 65536 bytes, use type file for unlimited size data. The parsed content of the Vault Item is a String.
file The symmetric Item Encryption Key for an arbitrary encrypted file or stream data. Might be either an encrypted file stored in a lockbox (size quotas apply), or stored by an external app outside of VESvault (such as centralized or distributed cloud storage). The parsed content of the Vault Item is a libVES.Cipher. a String Symmetric Cipher algorithm tag.
secret A scrambled Recovery Token, used in VESrecovery. The parsed content of the Vault Item is a following object: meta object Metadata. data Uint8Array Recovery Token. v String Scramble Algorithm version tag. n Int Number of tokens required to unscramble the Recovery Secret and achieve VESrecovery. b Int The base value for the recovery algorithm, distinct for each token in the scrambled Recovery Token set.
getId()
Promise(Int) Vault Item ID.
getType()
Promise(String) Vault Item Type.
getVaultEntries()
Promise(Array(object)) The vault entries that store the ciphertext pertaining to the Vault Item. vaultKey object id = VaultKey ID encData String Base64 encoded encrypted VaultItem data
getMeta()
Promise(object) Vault Item Metadata. Arbitrary key-value pairs, specific keys apply to certain Vault Item Types.
get()
Get the contents of the Vault Item, parsed according to the Type. The Vault Item must have a Vault Entry that pertains to an unlocked Vault Key in order to decrypt the contents.
Promise(…) The decrypted content, parsed according to the Vault Item Type.
libVES.Error Vault Key is not unlocked?
shareWith(vaults,content)
Deposit the content into the Vault Item, or change the sharing.
vaults Array(…) List of Vault References.
content The content to be deposited, formatted according to the Vault Item Type. null to change sharing rights to already deposited content.
Promise(libVES.ValutItem) Self if succeeded.
libVES.Error Malformed content or vault list?
libVES.External
Object libVES.External represents a reference from a VESvault object to some external entity.
getId()
Promise(Int) Vault Item ID.
getDomain()
Promise(String) External Domain Tag.
getExternalId()
Promise(String) External ID Reference.
libVES.Recovery
For internal use by VESvault.
getFriends()
Get list of VESrecovery Friends. Applicable only to the Owner's Recovery.
Trigger(Array(libVES.User)) List of Friends.
libVES.Error Not the owner of the recovery?
getFriendInfo(user)
Get a Recovery Info for a particular Friend. Applicable to the Owner's Recovery, or to the Friend's Recovery to get the Owner's info.
user libVES.User User to get Recovery Info for..
Trigger(object) Recovery Info obect. user libVES.User A friend who can assist in VESrecovery.
libVES.Error Not a valid friend for this VESrecovery?
getFriendsTotal()
Get total number of Friends who might be able to assist in this VESrecovery. Applicable only to Owner's Recovery.
Trigger(Int) Total number of Friends.
libVES.Error Not the owner of the recovery?
getFriendsRequired()
Get total required number of assistances to achieve VESrecovery.
Trigger(Int) Required total number of Friends to assist.
libVES.Error Not a valid recovery?
getFriendsAssisted()
Get number of Friends who have assisted in this VESrecovery. Applicable only to Owner's Recovery.
Trigger(Int) Number of Friends who have assisted.
libVES.Error Not the owner of the recovery?
getFriendsToGo()
Get number of Friends needed to assist to achieve VESrecovery, in addition to those who have already assisted. Applicable only to Owner's Recovery.
In case of foul assistance, i.e. when one or more Friends have shared invalid token for any reason, the returned value may depend on whether the Vault is unlocked or not. If the number of assisted friends is not less then the required number, the Vault is unlocked, and the VESrecovery cannot be achieved because of inconsistent data, the function will return 1.
Trigger(Int) Number of Friends to assist.
libVES.Error Not the owner of the recovery?
assist()
Provide VESrecovery assistance, i.e. share the Recovery Token back with the friend. Resets the ignore flag if it was set.
Promise(true) Success.
libVES.Error Not a friend?
revoke()
Revoke the VESrecovery provided, e.g. when fraud is suspected.
Not a reliable fraud protection. When in doubt, do not provide assistance at the first place. See security assessment in VES Whitepaper.
Promise(true) Success.
libVES.Error Not a friend?
ignore()
Flag the assistance request as ignored.
Promise(true) Success.
libVES.Error Not a friend?
recover()
Complete the VESrecovery.
The result is a Trigger. Call once, and wait until it resolves to true.
Trigger(true) The trigger resolves to null if recovery is still in progress, resolves to true once the recovery is completed.
libVES.Error Not the owner of the Recovery?