Skip to content

Commit a26d3f2

Browse files
committed
feat: updated faq
1 parent ba9aabb commit a26d3f2

6 files changed

Lines changed: 399 additions & 26 deletions

File tree

src/app/alternatives/privnote/page.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ export const metadata: Metadata = {
1818
"self destructing note",
1919
"burn after reading note",
2020
"send password securely",
21+
"self destructing file upload",
22+
"encrypted file send",
23+
"burn after download file",
2124
],
2225
openGraph: {
2326
type: "website",
@@ -73,6 +76,24 @@ const page: IntentPageData = {
7376
</p>
7477
),
7578
},
79+
{
80+
title: "Need to share a file, not just text?",
81+
body: (
82+
<p>
83+
Flowvault&apos;s sibling primitive,{" "}
84+
<Link href="/file/new" className="text-accent hover:underline">
85+
Encrypted File Send
86+
</Link>
87+
, does the same thing for documents and screenshots up to 10 MiB.
88+
Same URL-fragment-keyed AES-GCM wrap, same view cap and password
89+
options, plus a separate <em>secure delete link</em> you keep so
90+
you can destroy the upload immediately if the channel turns out to
91+
be untrusted. The encrypted bytes live in Cloud Storage; metadata
92+
and counters live in Firestore; the server never sees the
93+
filename, content, or the AES key.
94+
</p>
95+
),
96+
},
7697
{
7798
title: "Recipient loop",
7899
body: (

src/app/faq/page.tsx

Lines changed: 230 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import Link from "next/link";
55
import { DONATE_PATH, APP_URL } from "@/lib/config";
66

77
const FAQ_TITLE =
8-
"FAQ — Flowvault: encrypted online notepad, Cmd+K in-memory search, Markdown preview, Bring-Your-Own-Storage local vaults, trusted handover to a beneficiary, time-locked notes, Encrypted Send, encrypted backup & restore; ProtectedText / Standard Notes / CryptPad / Privnote / Bitwarden Send alternative";
8+
"FAQ — Flowvault: encrypted online notepad, Cmd+K in-memory search, Markdown preview, Bring-Your-Own-Storage local vaults, trusted handover to a beneficiary, time-locked notes, Encrypted Send, Encrypted File Send (10 MiB self-destructing file uploads with a secure delete link), encrypted backup & restore; ProtectedText / Standard Notes / CryptPad / Privnote / Bitwarden Send alternative";
99
const FAQ_DESCRIPTION =
10-
"Honest answers about Flowvault: how plausible-deniability hidden volumes work, how the Cmd+K command-palette search runs entirely in memory over the notebooks you've already unlocked (no persistent index, no server round-trip, deniability preserved), how the Markdown preview renders GitHub-flavored Markdown safely (HTML blocked, external images click-to-load, no-referrer links, syntax-highlighted code), how Bring-Your-Own-Storage local vaults keep the entire ciphertext on your own disk as a single .flowvault file, how the trusted handover releases a vault to a beneficiary if you stop checking in, how drand-backed time-locked notes keep messages sealed until a future date, how Encrypted Send creates self-destructing one-time links with view caps and optional passwords, how zero-knowledge .fvault backup and restore let you migrate or self-host without decrypting anything server-side, and how Flowvault compares to ProtectedText, Standard Notes, CryptPad, Privnote, OneTimeSecret, PrivateBin, Yopass, Notesnook, Joplin, Obsidian, Bitwarden Send, 1Password Share, and Skiff Notes.";
10+
"Honest answers about Flowvault: how plausible-deniability hidden volumes work, how the Cmd+K command-palette search runs entirely in memory over the notebooks you've already unlocked (no persistent index, no server round-trip, deniability preserved), how the Markdown preview renders GitHub-flavored Markdown safely (HTML blocked, external images click-to-load, no-referrer links, syntax-highlighted code), how Bring-Your-Own-Storage local vaults keep the entire ciphertext on your own disk as a single .flowvault file, how the trusted handover releases a vault to a beneficiary if you stop checking in, how drand-backed time-locked notes keep messages sealed until a future date, how Encrypted Send creates self-destructing one-time links with view caps and optional passwords, how Encrypted File Send adds 10 MiB self-destructing file uploads with a separate secure delete link, how zero-knowledge .fvault backup and restore let you migrate or self-host without decrypting anything server-side, and how Flowvault compares to ProtectedText, Standard Notes, CryptPad, Privnote, OneTimeSecret, PrivateBin, Yopass, Notesnook, Joplin, Obsidian, Bitwarden Send, 1Password Share, and Skiff Notes.";
1111

1212
export const metadata: Metadata = {
1313
title: FAQ_TITLE,
@@ -35,9 +35,14 @@ export const metadata: Metadata = {
3535
"drand tlock",
3636
"plausible deniability notes",
3737
"encrypted send",
38+
"encrypted file send",
3839
"one-time secret link",
3940
"self-destructing note",
41+
"self-destructing file upload",
42+
"secure file sharing",
4043
"burn after reading",
44+
"burn after download file",
45+
"secure delete link",
4146
"encrypted notepad backup",
4247
"zero-knowledge backup file",
4348
"Flowvault backup",
@@ -1289,12 +1294,16 @@ const FEATURES: QA[] = [
12891294
q: "Does Encrypted Send support files or just text?",
12901295
a: (
12911296
<>
1292-
Text only for now. Plaintext is capped at 128 KiB &mdash;
1293-
plenty for credentials, recovery phrases, configs, a long
1294-
paragraph of context. File attachments are on the roadmap and
1295-
would use Firebase Storage with a similar URL-fragment-keyed
1296-
wrap; they&rsquo;ll ship when we can do it without bloating
1297-
the threat model.
1297+
Encrypted Send itself is text-only (plaintext capped at
1298+
128&nbsp;KiB). For files, use the sibling{" "}
1299+
<Strong>Encrypted File Send</Strong> at{" "}
1300+
<Link href="/file/new" className="text-accent hover:underline">
1301+
/file/new
1302+
</Link>{" "}
1303+
&mdash; same threat model, same URL-fragment-keyed AES-GCM
1304+
wrap, but sized for documents and screenshots up to
1305+
10&nbsp;MiB. The encrypted bytes live in Cloud Storage rather
1306+
than Firestore. See the dedicated entries just below.
12981307
</>
12991308
),
13001309
},
@@ -1312,6 +1321,193 @@ const FEATURES: QA[] = [
13121321
</>
13131322
),
13141323
},
1324+
{
1325+
q: "What is Encrypted File Send?",
1326+
a: (
1327+
<>
1328+
The file-shaped sibling of Encrypted Send. Drop a file at{" "}
1329+
<Link href="/file/new" className="text-accent hover:underline">
1330+
/file/new
1331+
</Link>{" "}
1332+
(up to <Strong>10&nbsp;MiB</Strong>), pick how long it lives
1333+
(max <Strong>7 days</Strong>) and how many times it can be
1334+
downloaded (default 1, up to 10), and you get back{" "}
1335+
<Strong>two</Strong> links:
1336+
<ul className="mt-2 list-disc space-y-1 pl-5">
1337+
<li>
1338+
A <Strong>download link</Strong> for the recipient
1339+
(<Code>useflowvault.com/file/&lt;id&gt;#k=&lt;key&gt;</Code>).
1340+
</li>
1341+
<li>
1342+
A <Strong>secure delete link</Strong> for you to keep
1343+
(<Code>
1344+
useflowvault.com/file/&lt;id&gt;/delete#t=&lt;token&gt;
1345+
</Code>) &mdash; opening it lets you destroy the upload
1346+
immediately, before the cap or expiry.
1347+
</li>
1348+
</ul>
1349+
<p className="mt-3">
1350+
Optional password gate works the same way as Encrypted
1351+
Send. Read the{" "}
1352+
<Link
1353+
href="/blog/encrypted-file-send-zero-knowledge-uploads"
1354+
className="text-accent hover:underline"
1355+
>
1356+
File Send deep dive
1357+
</Link>{" "}
1358+
for the full protocol walkthrough.
1359+
</p>
1360+
</>
1361+
),
1362+
},
1363+
{
1364+
q: "How is the file actually encrypted?",
1365+
a: (
1366+
<>
1367+
<p>
1368+
AES-256-GCM in your browser before any byte leaves your
1369+
device. The exact key tree:
1370+
</p>
1371+
<ol className="mt-2 list-decimal space-y-1 pl-5">
1372+
<li>
1373+
A random 256-bit key <Code>K</Code> is generated client-side.
1374+
It travels in the URL fragment (<Code>#k=…</Code>); browsers
1375+
never transmit fragments to servers.
1376+
</li>
1377+
<li>
1378+
If a password is set, an Argon2id key is derived from it
1379+
(64&nbsp;MiB / 3 iterations) and concatenated with{" "}
1380+
<Code>K</Code> to form the base material.
1381+
</li>
1382+
<li>
1383+
Two HKDF subkeys are derived: a{" "}
1384+
<Code>contentKey</Code> (used to AEAD-encrypt the file
1385+
bytes, uploaded to Cloud Storage) and a{" "}
1386+
<Code>metadataKey</Code> (used to AEAD-encrypt a small JSON
1387+
blob with the filename, MIME type, and size, stored in
1388+
Firestore).
1389+
</li>
1390+
<li>
1391+
A separate random 256-bit <Strong>delete token</Strong> is
1392+
generated. The server stores only its{" "}
1393+
<Strong>SHA-256 digest</Strong>; the raw token lives in
1394+
your secure delete link, so possession of the link is the
1395+
only thing that authorizes deletion.
1396+
</li>
1397+
</ol>
1398+
<p className="mt-3">
1399+
Direct reads on the Storage object and the Firestore
1400+
document are denied by rules. The only path to the bytes is{" "}
1401+
<Code>readFileSend</Code>, a Cloud Function that atomically
1402+
consumes a download in a Firestore transaction and returns a
1403+
5-minute v4 signed URL.
1404+
</p>
1405+
</>
1406+
),
1407+
},
1408+
{
1409+
q: "What does the server actually see for a file send?",
1410+
a: (
1411+
<>
1412+
Same disclosure standard as the rest of Flowvault. The server
1413+
sees:
1414+
<ul className="mt-2 list-disc space-y-1 pl-5">
1415+
<li>
1416+
The opaque ciphertext bytes in Cloud Storage at{" "}
1417+
<Code>fileSends/&lt;id&gt;</Code> (file size + 28 bytes of
1418+
AEAD overhead).
1419+
</li>
1420+
<li>
1421+
A small encrypted metadata blob in Firestore (server
1422+
can&apos;t open it).
1423+
</li>
1424+
<li>
1425+
Expiry, max downloads, current download count.
1426+
</li>
1427+
<li>
1428+
A boolean <Code>passwordProtected</Code> flag and, when
1429+
set, a 16-byte Argon2id salt &mdash; useless without the
1430+
password and the URL fragment.
1431+
</li>
1432+
<li>
1433+
The 32-byte SHA-256 of the delete token. Useless without
1434+
the original token.
1435+
</li>
1436+
</ul>
1437+
<p className="mt-3">
1438+
It does <em>not</em> see the filename, MIME type, file
1439+
content, AES key, password, delete token, or any account /
1440+
email / persistent identifier &mdash; because none exist.
1441+
</p>
1442+
</>
1443+
),
1444+
},
1445+
{
1446+
q: "Can Flowvault delete a file send for me?",
1447+
a: (
1448+
<>
1449+
Two ways an upload gets removed, both server-side:
1450+
<ul className="mt-2 list-disc space-y-1 pl-5">
1451+
<li>
1452+
The recipient consumes the final allowed download. The
1453+
Cloud Function deletes the Firestore doc immediately and
1454+
the scheduled <Code>fileSendsSweep</Code> drops the
1455+
Storage object on the next tick (after the 5-minute
1456+
signed-URL grace window expires).
1457+
</li>
1458+
<li>
1459+
The expiry passes. <Code>fileSendsSweep</Code> deletes
1460+
both the doc and the object on the next hourly run.
1461+
</li>
1462+
</ul>
1463+
<p className="mt-3">
1464+
You can also force an immediate delete yourself by opening
1465+
your <Strong>secure delete link</Strong>. The Cloud Function{" "}
1466+
<Code>deleteFileSend</Code> SHA-256s the token from your URL
1467+
fragment, compares it to the stored hash in constant-ish
1468+
time, and (on match) drops the Storage object plus the
1469+
Firestore document. We can&rsquo;t recover the upload after
1470+
that, and we can&rsquo;t do this on your behalf because we
1471+
never stored the raw token.
1472+
</p>
1473+
</>
1474+
),
1475+
},
1476+
{
1477+
q: "Why 10 MiB and 7 days, exactly?",
1478+
a: (
1479+
<>
1480+
File Send is deliberately sized for documents and
1481+
screenshots, not large transfers. <Strong>10&nbsp;MiB</Strong>{" "}
1482+
is the cap because that&rsquo;s the line where browser
1483+
encryption + Cloud Function + signed-URL plumbing stays
1484+
snappy on a phone over 4G; above it the better tool is
1485+
Bitwarden Send Files, OnionShare, or Magic Wormhole.{" "}
1486+
<Strong>7 days</Strong> is the retention cap because, in
1487+
practice, almost every legitimate use case finishes within
1488+
72&nbsp;hours, and a hard ceiling reduces the window where a
1489+
forgotten upload can leak. The cap can be raised in a future
1490+
release, but it will stay scoped to ephemeral file transfer
1491+
rather than &ldquo;cloud storage.&rdquo;
1492+
</>
1493+
),
1494+
},
1495+
{
1496+
q: "What if I lose the secure delete link?",
1497+
a: (
1498+
<>
1499+
Same answer as &ldquo;what if I lose my password&rdquo; for the
1500+
rest of Flowvault: we can&apos;t recover it. The server only
1501+
ever stored the SHA-256 of the delete token; the raw token
1502+
existed exactly once, in the link we showed you on the
1503+
success screen. Without it, the upload sits until the expiry
1504+
or the download cap is consumed and then gets swept. Treat
1505+
the secure delete link the same way you treat the download
1506+
link: copy it, save it somewhere you control, understand we
1507+
can&apos;t re-derive it later.
1508+
</>
1509+
),
1510+
},
13151511
];
13161512

13171513
const MARKDOWN: QA[] = [
@@ -1568,9 +1764,10 @@ const BYOS: QA[] = [
15681764
corresponds to. Your browser never uploads the ciphertext or
15691765
the file name to us. The one caveat is the editor chrome: if
15701766
you use server-dependent features while a local vault is
1571-
open &mdash; time-locked notes composition, Encrypted Send
1572-
&mdash; those specific flows still talk to our backend for
1573-
their own documents (a time-locked capsule, a send record),
1767+
open &mdash; time-locked notes composition, Encrypted Send,
1768+
Encrypted File Send &mdash; those specific flows still talk
1769+
to our backend for their own documents (a time-locked
1770+
capsule, a send record, a file-send ciphertext object),
15741771
same as they would from a hosted vault. They never see your
15751772
local vault&apos;s plaintext or ciphertext.
15761773
</>
@@ -1669,14 +1866,15 @@ const BYOS: QA[] = [
16691866
),
16701867
},
16711868
{
1672-
q: "What about time-locked notes and Encrypted Send from a local vault?",
1869+
q: "What about time-locked notes, Encrypted Send, and Encrypted File Send from a local vault?",
16731870
a: (
16741871
<>
16751872
Those still work &mdash; they have nothing to do with where
1676-
your <em>vault</em> lives. Composing a time-locked note or an
1677-
Encrypted Send from the editor stores the one-shot capsule /
1678-
send document in our backend the same way as always; only the
1679-
notebook text lives in your local file.
1873+
your <em>vault</em> lives. Composing a time-locked note, an
1874+
Encrypted Send, or an Encrypted File Send from the editor
1875+
stores the one-shot capsule / send document / file ciphertext
1876+
in our backend the same way as always; only the notebook text
1877+
lives in your local file.
16801878
</>
16811879
),
16821880
},
@@ -1872,8 +2070,10 @@ const BACKUP: QA[] = [
18722070
a: (
18732071
<>
18742072
Yes. The whole stack &mdash; Next.js frontend, Cloud Functions
1875-
(the trusted-handover release sweep and the Encrypted Send read
1876-
path), and Firestore security rules &mdash; is in one public
2073+
(the trusted-handover release sweep, the Encrypted Send /
2074+
File Send read &amp; delete paths, and the file-send sweep),
2075+
Cloud Storage rules, and Firestore security rules &mdash;
2076+
is in one public
18772077
repository. Bring your own Firebase project, deploy the rules
18782078
and Functions, point the frontend at it, and drop a{" "}
18792079
<Code>.fvault</Code> file onto <Code>/restore</Code>. Because
@@ -2234,8 +2434,10 @@ export default function FAQPage() {
22342434
already unlocked, Bring-Your-Own-Storage local vaults stored
22352435
as a single <Code>.flowvault</Code> file on your device,
22362436
the trusted handover to a beneficiary, drand-backed
2237-
time-locked notes, Encrypted Send, <Code>.fvault</Code>{" "}
2238-
encrypted backups and restore, and how Flowvault compares
2437+
time-locked notes, Encrypted Send, Encrypted File Send (10
2438+
MiB self-destructing file uploads with a separate secure
2439+
delete link), <Code>.fvault</Code> encrypted backups and
2440+
restore, and how Flowvault compares
22392441
to ProtectedText, Standard Notes, CryptPad, and other
22402442
alternatives. If yours isn&apos;t here, open an issue on
22412443
GitHub.
@@ -2248,7 +2450,7 @@ export default function FAQPage() {
22482450
/>
22492451
<Section title="Security" items={SECURITY} />
22502452
<Section
2251-
title="Trusted handover & time-locked notes"
2453+
title="Trusted handover, time-locked notes, Encrypted Send & File Send"
22522454
items={FEATURES}
22532455
/>
22542456
<Section title="Using Flowvault" items={USAGE} />
@@ -2314,6 +2516,13 @@ export default function FAQPage() {
23142516
>
23152517
Encrypted Send vs Bitwarden Send vs Privnote
23162518
</Link>
2519+
, a deep dive on{" "}
2520+
<Link
2521+
href="/blog/encrypted-file-send-zero-knowledge-uploads"
2522+
className="text-accent hover:underline"
2523+
>
2524+
Encrypted File Send
2525+
</Link>
23172526
, the{" "}
23182527
<Link
23192528
href="/blog/encrypted-backup-fvault-format"

0 commit comments

Comments
 (0)