| 1 | {{define "title"}}Vault — CONTRA{{end}} |
| 2 | {{define "brand"}}<a rst-shell-brand href="/">CONTRA</a>{{end}} |
| 3 | {{define "head"}}<script type="module" src="{{asset "static/pages/vault.js"}}"></script>{{end}} |
| 4 | |
| 5 | {{define "content"}} |
| 6 | <h1>Your vault</h1> |
| 7 | |
| 8 | {{/* The counterfoil — the server's half of the ticket, and everything on |
| 9 | it is something the server already holds: that you have a session, |
| 10 | which vaults you can reach, and their opaque ids. It prints on the |
| 11 | tint block because that is what a counterfoil is, and it ends at the |
| 12 | perforation below. */}} |
| 13 | <div data-counterfoil> |
| 14 | |
| 15 | {{/* Signing in is not unlocking. The session proved who you are; the keys |
| 16 | come from a wrap this server cannot open, so the page asks again and |
| 17 | does the work in the browser. */}} |
| 18 | <form data-unlock method="post" action="#"> |
| 19 | <p>Signing in proved who you are. Opening the vault needs your passphrase |
| 20 | again, because the key comes from something this server cannot read.</p> |
| 21 | <p> |
| 22 | <label for="passphrase">Passphrase</label> |
| 23 | <input id="passphrase" name="passphrase" type="password" |
| 24 | autocomplete="current-password" required> |
| 25 | </p> |
| 26 | <p><button type="submit">Unlock</button></p> |
| 27 | <div data-status aria-live="polite"></div> |
| 28 | </form> |
| 29 | |
| 30 | {{/* Shown only when there is more than one vault to choose between. The |
| 31 | labels come out of the keysets, so this list is built from names the |
| 32 | server has never seen. */}} |
| 33 | <p data-vault-choice hidden> |
| 34 | <label for="vault-picker">Vault</label> |
| 35 | <select id="vault-picker" data-vault-picker></select> |
| 36 | </p> |
| 37 | |
| 38 | </div> |
| 39 | |
| 40 | {{/* The tear-line, and the only one in the app. Everything above it is |
| 41 | what this server holds and could hand to anyone who stole it: a |
| 42 | public key, opaque ids, counts, the times of day you connected. |
| 43 | Everything below it was opened in this browser and the server has |
| 44 | never seen a byte of it in the clear. |
| 45 | |
| 46 | Every product in this category has this boundary. Most would find |
| 47 | it awkward to draw honestly, which is the reason to draw it. */}} |
| 48 | <div data-tear><span>held by this server ↑</span><span>opened only here ↓</span></div> |
| 49 | |
| 50 | <div data-vault hidden></div> |
| 51 | |
| 52 | {{/* Sharing. Hidden until the vault is open, because everything in it needs |
| 53 | the vault key: sharing seals the keyset to somebody, and removing |
| 54 | somebody re-seals every item under a new one. */}} |
| 55 | <section data-sharing hidden> |
| 56 | <h2>Sharing</h2> |
| 57 | |
| 58 | <p>Your account id is <code data-my-account></code>. Give it to somebody who |
| 59 | wants to share a vault with you — there is no directory to look you up in, |
| 60 | and deliberately so: an address-to-account lookup would let anyone test |
| 61 | whether an address has an account here.</p> |
| 62 | |
| 63 | <form data-share-form method="post" action="#"> |
| 64 | <p> |
| 65 | <label for="account_id">Share with this account id</label> |
| 66 | <input id="account_id" name="account_id" type="text" autocomplete="off" |
| 67 | spellcheck="false" required |
| 68 | placeholder="32 hexadecimal characters"> |
| 69 | </p> |
| 70 | <p><button type="submit">Share this vault</button></p> |
| 71 | </form> |
| 72 | |
| 73 | <h3>Members</h3> |
| 74 | <ul data-members></ul> |
| 75 | |
| 76 | {{/* PROTOCOL.md's revocation answer, all three parts, before the button |
| 77 | rather than after it. The third is the one every product in this |
| 78 | category quietly omits. */}} |
| 79 | <p data-kind="warning">Removing somebody does three things, and only two of |
| 80 | them are what people expect. Their access stops immediately. The vault gets |
| 81 | a new key, and every item is re-encrypted under it. But |
| 82 | <strong>anything they already downloaded is still theirs</strong> — no |
| 83 | design can take that back, and ours does not pretend to.</p> |
| 84 | |
| 85 | <p> |
| 86 | <label> |
| 87 | <input type="checkbox" data-understood> |
| 88 | I understand that removing somebody cannot un-download what they already |
| 89 | have. |
| 90 | </label> |
| 91 | </p> |
| 92 | |
| 93 | <p data-share-status aria-live="polite"></p> |
| 94 | </section> |
| 95 | |
| 96 | {{/* PROTOCOL.md: the reprint flow must be obvious rather than buried, and |
| 97 | the nag to enrol a second device lives beside it. Both are the |
| 98 | mitigation for the one loss mode the Account Key introduced. */}} |
| 99 | <p><a href="/kit">Your printed kit</a> — reprint the Account Key card, or |
| 100 | issue a new recovery sheet. <a href="/device">This device</a> — approve |
| 101 | another browser, or give this one your Account Key.</p> |
| 102 | |
| 103 | |
| 104 | <form method="post" action="/auth/signout"> |
| 105 | <button type="submit">Sign out</button> |
| 106 | </form> |
| 107 | {{end}} |
| 108 | |