InnoVault Client
The very first step is to register with and create an InnoVault account. The InnoVault Admin Console requires a password, but this password is never stored on Tozny’s server. Instead, it’s used to derive an authentication key used locally to sign a login challenge. Tozny never sees your password and can never expose it to third parties.
The client management screen allows managers to create new clients (and retrieve backed-up keys and credentials in an emergency).

Client credentials are presented both in traditional input fields (for easy reference) and in a handy JSON format for use with the e3db CLI utility.

InnoVault forms require a unique name, a record type, and a client with which they will be associated.
The Form
For this example, we’ll build a simple voting form that can be used by community groups to poll for and surface opinions. The impetus behind such a form is to keep voting private while still keeping track of who has or hasn’t voted and collating any free-form comments submitted independently. We will keep the names of voters and their votes together in the form, but don’t want anyone to see that association publicly by mistake. The form as such is relatively simple:<html>
<head>
<script type="text/javascript" src="https://js.innovault.io/1.0.2/innovault-web.min.js" integrity="sha384-7Fnanu/5+Mu87uh9hZfwbp00SSCA8y5u1F/DUQe2u9wrrCxTVI/aaCAD5qS68RKE" crossorigin="anonymous"></script>
</head>
<body>
<h1>Community Poll
<form name="poll" method="post">
<p>
<label for="fullname">Full Name</label>
<input name="fullname" />
</p>
<p>
<label>Should we have speed bumps on Main St.?</label>
<input type="radio" name="vote" value="yes" checked />
</p>
<p>
<label>Should we cancel the summer BBQ?</label>
<input type="radio" name="bbq" value="yes" /><label for="yes">Yes</label>
<input type="radio" name="bbq" value="no" checked /><label for="no">No</label>
</p>
<p>
<label for="comments">Other Comments</label>
<textarea name="comments"></textarea>
</p>
<p>
<button type="button" onclick="submitVote()">Vote!</button>
</p>
</form>
<script type="text/javascript">
function submitVote() {
var token = '...';
var vote = {
fullname: document.forms.poll.fullname.value,
vote: document.forms.poll.vote.value,
bbq: document.forms.poll.bbq.value,
comments: document.forms.poll.comments.value
};
window.innovault.web.sdk.submit(token, vote)
.then(function(data) {
// Clear out old values in the form to prevent duplicate submissions
document.forms.poll.vote.value = 'yes';
document.forms.poll.bbq.value = 'no';
document.forms.poll.fullname.value = document.forms.poll.comments.value = '';
alert('Thanks for voting!');
});
return false;
}
</script>
</body>
</html>
The community members are voting on two potentially controversial issues: installing speed bumps on the town’s main street and canceling a beloved community event. Some might be interested in leaving further comments that should be collected and collated.
This example is using the web variant of the InnoVault SDK that permits programmatic control over the form submission. This is due to the fact that radio buttons (used in the vote) are not supported via InnoVault’s easy SDK variant. If the form were a simple text entry (i.e. no voting), this HTML could be drastically simplified. Please take some time to review the documentation of the Easy SDK variant to see how it differs (and makes forms simple to encrypt).
When our community members submit this form, the data will be collected into a JSON blob, encrypted in the browser, then submitted to InnoVault for storage until you’re ready to use it.
Extracting Data
Retrieving the data can take one of two forms. On the one hand, a developer could use the client credentials created earlier with the e3db CLI to read the data directly. This would help a developer quickly audit that data is flowing from the form to the database as expected, but runs the risk of exposing that data to the developer as well.
While not an ideal data retrieval route, privileged developers can use the e3db CLI to query for and inspect records written by InnoVault forms.
The e3db SDK
At the time of this writing, there are 4 different SDKs available for use with e3db – Go, Ruby, PHP, and Java. All four SDKs are fairly similar in structure, so following these examples in your language of preference will be relatively straight-forward. For the sake of this example, we will use the Ruby SDK.Voter Names
Every voter has specified their names in a field called fullname. The e3db SDK will return all fields, but our script can ignore the rest of the data and only collate the field we care about. This script will fetch all votes, collect the voters’ names into a list, randomize the list, then print the list out to the console:require 'e3db'
config = E3DB::Config.load_profile('ex')
config.logging = false
client = E3DB::Client.new(config)
voters = Array.new
client.query(type: 'vote').each do |record|
voters.push(record.data[:fullname])
end
puts voters.shuffle
Vote Tallies
Along a similar vein, we want to know how many people voted yes or no to our two questions. What we don’t want to know is who voted for which option. This script will again fetch all votes, but it will only collect the votes themselves into specific counters. Once all votes are tabulated, they’re printed to the console:require 'e3db'
config = E3DB::Config.load_profile('ex')
config.logging = false
client = E3DB::Client.new(config)
votes = 0
speedbumps = 0
bbq = 0
client.query(type: 'vote').each do |record|
votes += 1
if record.data[:vote] == 'yes'
speedbumps += 1
end
if record.data[:bbq] == 'yes'
bbq += 1
end
end
puts('Total Votes: ' + votes.to_s)
puts('In favor of speed bumps: ' + speedbumps.to_s)
puts('In favor of cancelling the BBQ: ' + bbq.to_s)
Assuming a total of 8 community members have voted, the results of this vote (and the script to tabulate them) could look something like:

The script counts “yes” votes and keeps track of the total number of voters, making it easy to determine which option “won.”
Comment Collation
Finally, we want to keep track of any freeform comments left by our voters. As with the previous two examples, while the data is important, we don’t want to keep track of who commented what in the event that it’s sensitive information. Instead, our script will gather all of the votes, collect the various comments into an array, randomize it, then print the array to the console:require 'e3db'
config = E3DB::Config.load_profile('ex')
config.logging = false
client = E3DB::Client.new(config)
comments = Array.new
client.query(type: 'vote').each do |record|
comments.push(record.data[:comments])
end
puts comments.shuffle
This script is almost identical to the one that collected voter names (as both fullname and comments are simple text fields, that’s to be expected). In a more sophisticated example, this data could be exported as a comma-delimited list and piped to a CSV file for import into a spreadsheet application.