diff --git a/wasm/dist-repl/index.html b/wasm/dist-repl/index.html index cd6cb93..c6adfa1 100644 --- a/wasm/dist-repl/index.html +++ b/wasm/dist-repl/index.html @@ -44,8 +44,37 @@

unlock

-

enter a password — transcripts are encrypted with it locally. - a fresh password starts a fresh vault.

+

type a password to unlock or create a vault. every keystroke and + transcript line stays inside your browser — nothing leaves + this tab.

+
+ how the encryption works +
    +
  • your password is run through PBKDF2 (200,000 + iterations, SHA-256) with a random 32-byte salt generated + once per device and stored in localStorage.
  • +
  • that derives an AES-GCM 256-bit key. all + transcripts are encrypted with this key before any + localStorage.setItem() call.
  • +
  • the vault id is + SHA-256(password || salt) — different + passwords on the same device address completely independent + vaults. wrong password = decryption fails, you don't see + other vaults' contents.
  • +
  • same protocol as unsandbox's vault design, implemented + on the native crypto.subtle API instead of a + shipped CryptoJS bundle. source: + crypto.js.
  • +
  • passwords are never sent anywhere — not to lumbda.com, + not to a backend, not to a worker. nothing to leak in + transit because nothing transits.
  • +
  • ephemeral skips the vault entirely — + nothing is written to disk; closing the tab loses everything. + use this on a shared machine when persistence would be a + footgun.
  • +
+
diff --git a/wasm/dist-repl/repl.css b/wasm/dist-repl/repl.css index 19dc1f5..ed7b792 100644 --- a/wasm/dist-repl/repl.css +++ b/wasm/dist-repl/repl.css @@ -78,6 +78,36 @@ body.repl { font-size: 0.8rem; min-height: 1.2em; } +.lock-explain { + margin: 0.4rem 0 0; + font-size: 0.78rem; + color: var(--muted); +} +.lock-explain summary { + cursor: pointer; + color: var(--green); + user-select: none; +} +.lock-explain summary:hover { text-decoration: underline; } +.lock-explain ul { + margin: 0.5rem 0 0; + padding-left: 1.1rem; + display: grid; + gap: 0.3rem; +} +.lock-explain li { line-height: 1.45; } +.lock-explain code { + background: var(--code-bg); + padding: 0 0.2em; + border-radius: 2px; + font-size: 0.92em; +} +.lock-explain a { + color: var(--green); + text-decoration: none; +} +.lock-explain a:hover { text-decoration: underline; } +.lock-explain strong { color: var(--fg); } /* ─── Tab bar ──────────────────────────────────────────────────── */ diff --git a/wasm/repl/index.html b/wasm/repl/index.html index cd6cb93..c6adfa1 100644 --- a/wasm/repl/index.html +++ b/wasm/repl/index.html @@ -44,8 +44,37 @@

unlock

-

enter a password — transcripts are encrypted with it locally. - a fresh password starts a fresh vault.

+

type a password to unlock or create a vault. every keystroke and + transcript line stays inside your browser — nothing leaves + this tab.

+
+ how the encryption works +
    +
  • your password is run through PBKDF2 (200,000 + iterations, SHA-256) with a random 32-byte salt generated + once per device and stored in localStorage.
  • +
  • that derives an AES-GCM 256-bit key. all + transcripts are encrypted with this key before any + localStorage.setItem() call.
  • +
  • the vault id is + SHA-256(password || salt) — different + passwords on the same device address completely independent + vaults. wrong password = decryption fails, you don't see + other vaults' contents.
  • +
  • same protocol as unsandbox's vault design, implemented + on the native crypto.subtle API instead of a + shipped CryptoJS bundle. source: + crypto.js.
  • +
  • passwords are never sent anywhere — not to lumbda.com, + not to a backend, not to a worker. nothing to leak in + transit because nothing transits.
  • +
  • ephemeral skips the vault entirely — + nothing is written to disk; closing the tab loses everything. + use this on a shared machine when persistence would be a + footgun.
  • +
+
diff --git a/wasm/repl/repl.css b/wasm/repl/repl.css index 19dc1f5..ed7b792 100644 --- a/wasm/repl/repl.css +++ b/wasm/repl/repl.css @@ -78,6 +78,36 @@ body.repl { font-size: 0.8rem; min-height: 1.2em; } +.lock-explain { + margin: 0.4rem 0 0; + font-size: 0.78rem; + color: var(--muted); +} +.lock-explain summary { + cursor: pointer; + color: var(--green); + user-select: none; +} +.lock-explain summary:hover { text-decoration: underline; } +.lock-explain ul { + margin: 0.5rem 0 0; + padding-left: 1.1rem; + display: grid; + gap: 0.3rem; +} +.lock-explain li { line-height: 1.45; } +.lock-explain code { + background: var(--code-bg); + padding: 0 0.2em; + border-radius: 2px; + font-size: 0.92em; +} +.lock-explain a { + color: var(--green); + text-decoration: none; +} +.lock-explain a:hover { text-decoration: underline; } +.lock-explain strong { color: var(--fg); } /* ─── Tab bar ──────────────────────────────────────────────────── */ diff --git a/www/repl/index.html b/www/repl/index.html index cd6cb93..c6adfa1 100644 --- a/www/repl/index.html +++ b/www/repl/index.html @@ -44,8 +44,37 @@

unlock

-

enter a password — transcripts are encrypted with it locally. - a fresh password starts a fresh vault.

+

type a password to unlock or create a vault. every keystroke and + transcript line stays inside your browser — nothing leaves + this tab.

+
+ how the encryption works +
    +
  • your password is run through PBKDF2 (200,000 + iterations, SHA-256) with a random 32-byte salt generated + once per device and stored in localStorage.
  • +
  • that derives an AES-GCM 256-bit key. all + transcripts are encrypted with this key before any + localStorage.setItem() call.
  • +
  • the vault id is + SHA-256(password || salt) — different + passwords on the same device address completely independent + vaults. wrong password = decryption fails, you don't see + other vaults' contents.
  • +
  • same protocol as unsandbox's vault design, implemented + on the native crypto.subtle API instead of a + shipped CryptoJS bundle. source: + crypto.js.
  • +
  • passwords are never sent anywhere — not to lumbda.com, + not to a backend, not to a worker. nothing to leak in + transit because nothing transits.
  • +
  • ephemeral skips the vault entirely — + nothing is written to disk; closing the tab loses everything. + use this on a shared machine when persistence would be a + footgun.
  • +
+
diff --git a/www/repl/repl.css b/www/repl/repl.css index 19dc1f5..ed7b792 100644 --- a/www/repl/repl.css +++ b/www/repl/repl.css @@ -78,6 +78,36 @@ body.repl { font-size: 0.8rem; min-height: 1.2em; } +.lock-explain { + margin: 0.4rem 0 0; + font-size: 0.78rem; + color: var(--muted); +} +.lock-explain summary { + cursor: pointer; + color: var(--green); + user-select: none; +} +.lock-explain summary:hover { text-decoration: underline; } +.lock-explain ul { + margin: 0.5rem 0 0; + padding-left: 1.1rem; + display: grid; + gap: 0.3rem; +} +.lock-explain li { line-height: 1.45; } +.lock-explain code { + background: var(--code-bg); + padding: 0 0.2em; + border-radius: 2px; + font-size: 0.92em; +} +.lock-explain a { + color: var(--green); + text-decoration: none; +} +.lock-explain a:hover { text-decoration: underline; } +.lock-explain strong { color: var(--fg); } /* ─── Tab bar ──────────────────────────────────────────────────── */