Request a file—without receiving plaintext in your infrastructure.
The shipped full-tier request flow, from one CLI command to browser encryption and local collection.
Create the request
dove request "the signed NDA" --from "Ada" --message "Please return the signed copy" \
--pin --expires 1d dove creates a request policy in the full-tier gate, encrypts the requester name, message, and description with the fragment secret, records the request locally, and prints a link such as https://share.example/r/<id>#fragment. Send the generated PIN separately if you used --pin.
The uploader needs only a browser. No dove install, account, extension, or access to your cloud is required.
What the uploader sees
- Opening
/r/<id>loads a static page and does not authorize or consume an upload. - The page reads
location.hashlocally, fetches opaque request metadata from/rmeta/<id>, and decrypts the requester name, message, and description in the browser. - If a PIN is required, the uploader enters it explicitly. The gate checks it online and locks after five wrong attempts; PIN verification alone does not start an upload.
- The uploader chooses one file and clicks Encrypt & send file. The page buffers and encrypts the file locally in the dove chunked container.
- The gate returns a short-lived, request-scoped S3 POST form. The browser uploads ciphertext, then calls the completion route after S3 confirms the object.
The current browser request path accepts one file up to 512 MiB. That ceiling is enforced by the presigned S3 POST policy. It is a current product limit, not a claim that a browser can safely handle every file below it on every device.
Watch and collect
dove requests
dove requests get <request-id>
dove requests get <request-id> --out ./incoming/signed-nda.pdf dove requests reads this machine’s local ledger and asks the gate for current status. A received row includes the locally decrypted filename and size. dove requests get downloads the ciphertext, authenticates every chunk, and saves plaintext on the requester’s machine.
One unreachable gate degrades only that row to unreachable; it does not hide the rest of the local ledger.
PIN is access; the fragment is confidentiality
For a file request, the optional PIN authorizes the upload at the gate. The high-entropy fragment secret encrypts the file and request metadata. The gate can see a submitted PIN and enforce attempts, expiry, and upload policy, but it never receives the fragment secret and cannot decrypt the file, filename, requester name, message, or description.
This differs from a PIN-locked outgoing share, where the share content key is derived from both PIN and fragment. Do not copy that derivation claim onto the request flow.
The local ledger is part of the key custody model
The requester’s durable record lives at ~/.config/dove/requests.json (or the XDG equivalent) and is mode 0600 on Unix. It stores the request ID, fragment, description, and creation time. The gate does not have a recovery copy of the fragment. Protect this file, exclude it from source control, and do not log or publish request links.
Request routes
| Route | Purpose | Side effect? |
|---|---|---|
GET /r/<id> | Static upload page | No |
GET /rmeta/<id> | Status and opaque encrypted request metadata | No |
GET /verify/<id>?pin=… | Rate-limited PIN pre-check | Failed attempts count |
GET /up/<id>?pin=… | Authorize and return a presigned S3 POST form | Upload handout attempt counts |
POST /done/<id>?pin=… | Confirm the object and encrypted filename metadata | Completes the request |