Make the recipient page yours—carefully.
The share page is deliberately replaceable, but its interaction model is part of the security boundary. Brand freely; preserve these invariants.
Current customization path
There is not yet a supported theme file or runtime page-plugin API. The current page is a self-contained HTML asset embedded in dove-core, packaged into the gate Lambda, and served at /d/<id>. Source-level customization works like this:
- Fork the page source and change its styles, mark, type, layout, and copy.
- Build it as one self-contained HTML document—no required third-party scripts.
- Replace
dove-core/assets/share.htmlwith the builtdist/share/index.html. - Run the relevant tests and inspect the generated asset for network calls.
- Re-run
dove provision fullto update the existing gate Lambda code.
This is an operator fork today. Upstream updates will not automatically merge into a customized embedded page. Diff the security behavior on every update.
The gate routes the page uses
| Route | Behavior | Consumes a download? |
|---|---|---|
GET /d/<id> | Returns the static page. Served even before policy lookup. | No |
GET /meta/<id> | Returns expiry, size, budgets, encrypted metadata, PIN-required and locked flags. | No |
GET /verify/<id>?pin=… | Checks and rate-limits the PIN without releasing ciphertext. | No |
GET /dl/<id>?pin=… | Checks policy, atomically decrements, then redirects to a 15-minute S3 URL. | Yes, on success |
GET /og.png | Returns the generic branded preview image. | No |
Non-negotiable interaction invariants
- Never transmit
location.hash. Do not add it to fetch URLs, analytics, errors, logs, query parameters, beacons, or crash reports. - Never start
/dlon load. Require an explicit human action so link unfurlers cannot spend one-time shares. - Metadata is free; ciphertext is not. Use
/metato render status and choose browser or CLI flow before the action. - Keep PIN verification separate. A PIN submit may call
/verify; it must not silently fetch the file. Announce remaining attempts and make locked state terminal. - Keep decryption local. Use WebCrypto or the CLI. Never send keys or plaintext to a convenience service.
- Preserve authenticated chunk handling. Reject wrong keys, changed data, reordering, and truncation; do not emit partial unauthenticated plaintext.
- Large files use the CLI. At 2 GB and above, show size and a complete
dove get <url>command instead of buffering the payload in-browser. - Install points to dove.sh. A share origin is operator-controlled and therefore not the canonical place to publish an inline installer.
Safe branding changes
Change color tokens, typefaces, border radius, layout density, illustrations, operator name, and the domain notice. Keep recognizable dove attribution near the local-decryption explanation, clearly display which domain hosts the page, and distinguish operator branding from a claim that dove.sh operates the share.
:root {
--paper: #fbfcff;
--ink: #111c2f;
--action: #164f8a;
--line: #d8e0ec;
} Prefer system or bundled fonts. A remote font or analytics script creates another network observer on a page holding a fragment secret and expands the page’s supply-chain surface.
States a custom page must cover
Ready, decrypting, browser save, large-file CLI handoff, missing fragment, unsupported browser, PIN required, verifying, wrong PIN with attempts remaining, locked, expired, download limit reached, missing share, integrity failure, and generic gate/network error. Focus the new state’s heading, use live regions for progress and errors, and support keyboard and paste on PIN input.
File-request pages
Status: designed, not released in the current CLI. The approved request flow reverses the transfer: a requester creates a PIN-protected request, the browser encrypts one selected file locally, and a short-lived gate-authorized upload places ciphertext in the requester’s infrastructure. Do not expose proposed dove request commands as shipped until they appear in the CLI source.