mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Merge pull request #2146 from PR0M3TH3AN/docs-remove-presigned-manifest-mode-1567500302751795913
📘 Align development docs with codebase behavior
This commit is contained in:
2 files changed
+35
-33
No files matched your search
@@ -43,7 +43,6 @@ Pick the flow that matches your source material. Supported S3 upload modes inclu
|
||||
1. **Browser-held S3 keys (trusted operator only):** Enter your S3 credentials in the Storage tab to upload directly from the browser.
|
||||
> **Security Warning:** This mode requires storing encrypted credentials in the browser's IndexedDB. While keys are encrypted at rest, they are decrypted in memory during use. Use this mode only on self-hosted, trusted deployments where you control the environment. Do not enter high-value credentials on public or untrusted instances.
|
||||
2. **Manual upload via provider console:** Upload your file to your storage provider (e.g., R2, S3) manually, then paste the public URL into the upload form.
|
||||
3. **Operator-provided presigned manifests:** Use a presigned JSON manifest prepared externally to authorize the upload without exposing long-lived credentials to the browser.
|
||||
|
||||
**Upload File (direct S3 upload)**:
|
||||
If you are using **Mode 1** (Browser-held keys), enter your credentials in the guided form or Storage tab. Optionally expand the **Advanced options** accordion to override pathing or access controls, then drop media files for bitvid to upload through the S3 API. The modal tracks progress, applies your metadata selections, auto-fills the primary `imeta` variant once the upload completes, and publishes the resulting URL back into the note automatically.
|
||||
|
||||
+35
-32
@@ -12,8 +12,6 @@ The storage system supports three primary modes for handling video uploads:
|
||||
The user enters S3 credentials (Access Key/Secret Key) into the Storage Tab. These keys are encrypted and stored in the browser's IndexedDB. This mode offers the smoothest UX but carries higher risk.
|
||||
2. **Manual upload via provider console:**
|
||||
The user uploads the file manually to their provider (e.g., R2 dashboard) and simply provides the public URL. This bypasses the need for the browser to hold write credentials.
|
||||
3. **Operator-provided presigned manifests:**
|
||||
The user provides a JSON manifest generated externally (e.g., by a CLI tool or backend service). This manifest contains presigned URLs for uploading parts, allowing the browser to upload without ever seeing the long-lived credentials.
|
||||
|
||||
## 1. Core Architecture: `StorageService`
|
||||
|
||||
@@ -55,26 +53,26 @@ All data is stored in **IndexedDB** under the database `bitvid-storage` and obje
|
||||
To balance security with usability (minimizing NIP-07/NIP-44 prompts), the system uses a dual-layer encryption approach:
|
||||
|
||||
1. **Layer 1: The Master Key (Session Key)**
|
||||
* A random 256-bit **AES-GCM** key is generated when the user first sets up storage.
|
||||
* This key is encrypted **once** using the user's Nostr Signer (NIP-44 or NIP-04) and stored as `encryptedMasterKey`.
|
||||
* **Unlocking:** When the user "unlocks" storage, the app requests the signer to decrypt this key. The decrypted Master Key is held in memory for the session.
|
||||
- A random 256-bit **AES-GCM** key is generated when the user first sets up storage.
|
||||
- This key is encrypted **once** using the user's Nostr Signer (NIP-44 or NIP-04) and stored as `encryptedMasterKey`.
|
||||
- **Unlocking:** When the user "unlocks" storage, the app requests the signer to decrypt this key. The decrypted Master Key is held in memory for the session.
|
||||
|
||||
2. **Layer 2: Payload Encryption**
|
||||
* Actual connection secrets (Access Keys, Secret Keys) are encrypted using the **Master Key** (AES-GCM).
|
||||
* This allows the app to save/load multiple connections during a session without re-prompting the user's signer for every single field.
|
||||
- Actual connection secrets (Access Keys, Secret Keys) are encrypted using the **Master Key** (AES-GCM).
|
||||
- This allows the app to save/load multiple connections during a session without re-prompting the user's signer for every single field.
|
||||
|
||||
## 2. Provider Adapter Pattern
|
||||
|
||||
The system uses an adapter pattern to support multiple providers.
|
||||
|
||||
* **Provider IDs:** Defined in `PROVIDERS` (e.g., `cloudflare_r2`, `aws_s3`, `generic_s3`).
|
||||
* **Test Handlers:** A `PROVIDER_TESTS` map routes connection tests to the appropriate handler.
|
||||
- **Provider IDs:** Defined in `PROVIDERS` (e.g., `cloudflare_r2`, `aws_s3`, `generic_s3`).
|
||||
- **Test Handlers:** A `PROVIDER_TESTS` map routes connection tests to the appropriate handler.
|
||||
|
||||
```javascript
|
||||
// js/services/storageService.js
|
||||
const PROVIDER_TESTS = {
|
||||
[PROVIDERS.R2]: testS3Connection,
|
||||
[PROVIDERS.S3]: testS3Connection, // Reuses S3 logic
|
||||
[PROVIDERS.S3]: testS3Connection, // Reuses S3 logic
|
||||
[PROVIDERS.GENERIC]: testS3Connection // Reuses S3 logic
|
||||
};
|
||||
```
|
||||
@@ -86,41 +84,46 @@ This design allows adding new providers (e.g., FTP, IPFS, etc.) by registering a
|
||||
Different providers require different configuration schemas.
|
||||
|
||||
### Generic S3 Provider (`generic_s3`)
|
||||
|
||||
The baseline schema for any S3-compatible service.
|
||||
|
||||
* **Payload (Encrypted):**
|
||||
* `endpoint`: Full URL to the S3 API (e.g., `https://s3.us-east-1.amazonaws.com`).
|
||||
* `region`: AWS Region (e.g., `us-east-1`).
|
||||
* `accessKeyId`: API Key ID.
|
||||
* `secretAccessKey`: API Secret.
|
||||
* `bucket`: Target bucket name.
|
||||
- **Payload (Encrypted):**
|
||||
- `endpoint`: Full URL to the S3 API (e.g., `https://s3.us-east-1.amazonaws.com`).
|
||||
- `region`: AWS Region (e.g., `us-east-1`).
|
||||
- `accessKeyId`: API Key ID.
|
||||
- `secretAccessKey`: API Secret.
|
||||
- `bucket`: Target bucket name.
|
||||
|
||||
### Cloudflare R2 Provider (`cloudflare_r2`)
|
||||
|
||||
A specialized profile of S3 with specific constraints to improve UX.
|
||||
|
||||
* **Payload (Encrypted):**
|
||||
* `accountId`: Cloudflare Account ID (used to construct the endpoint).
|
||||
* `accessKeyId` & `secretAccessKey`.
|
||||
* `bucket`: (Optional) Target bucket.
|
||||
* **Adapter Logic:**
|
||||
The `makeR2Client` adapter (`js/storage/r2-s3.js`) detects the `accountId` and automatically constructs the standard Cloudflare endpoint:
|
||||
`https://<accountId>.r2.cloudflarestorage.com`
|
||||
- **Payload (Encrypted):**
|
||||
- `accountId`: Cloudflare Account ID (used to construct the endpoint).
|
||||
- `accessKeyId` & `secretAccessKey`.
|
||||
- `bucket`: (Optional) Target bucket.
|
||||
- **Adapter Logic:**
|
||||
The `makeR2Client` adapter (`js/storage/r2-s3.js`) detects the `accountId` and automatically constructs the standard Cloudflare endpoint:
|
||||
`https://<accountId>.r2.cloudflarestorage.com`
|
||||
|
||||
## 4. Security & Privacy Warnings
|
||||
|
||||
### Local Storage & XSS
|
||||
* **Risk:** The encrypted data resides in the browser's **IndexedDB**. While encrypted at rest, a malicious script (XSS attack) running in the context of the application could potentially request the signer to decrypt the Master Key or read the decrypted key from memory if the session is active.
|
||||
* **Warning:** Because of this risk, **Mode 1 (Browser-held keys)** should only be used on **self-hosted, trusted deployments** where the operator controls the environment. Do not enter high-value credentials on public, untrusted, or shared instances.
|
||||
* **Mitigation:** The application must maintain strict Content Security Policy (CSP) and dependency hygiene to prevent XSS. Use Mode 2 or 3 for higher security assurance in untrusted environments.
|
||||
|
||||
- **Risk:** The encrypted data resides in the browser's **IndexedDB**. While encrypted at rest, a malicious script (XSS attack) running in the context of the application could potentially request the signer to decrypt the Master Key or read the decrypted key from memory if the session is active.
|
||||
- **Warning:** Because of this risk, **Mode 1 (Browser-held keys)** should only be used on **self-hosted, trusted deployments** where the operator controls the environment. Do not enter high-value credentials on public, untrusted, or shared instances.
|
||||
- **Mitigation:** The application must maintain strict Content Security Policy (CSP) and dependency hygiene to prevent XSS. Use Mode 2 for higher security assurance in untrusted environments.
|
||||
|
||||
### Ephemeral Key Derivation (Kind 22242)
|
||||
|
||||
To consistently derive or verify keys without publishing sensitive data, the system uses a **Storage Challenge Event**.
|
||||
|
||||
* **Kind:** `22242` (`NOTE_TYPES.STORAGE_CHALLENGE`)
|
||||
* **Purpose:** This event is created ephemerally to challenge the signer. The signature of this event is used as a seed to derive the encryption keys or to verify ownership.
|
||||
* **Privacy:** This event is **NEVER** published to relays. It exists solely in the local client memory during the unlocking process.
|
||||
- **Kind:** `22242` (`NOTE_TYPES.STORAGE_CHALLENGE`)
|
||||
- **Purpose:** This event is created ephemerally to challenge the signer. The signature of this event is used as a seed to derive the encryption keys or to verify ownership.
|
||||
- **Privacy:** This event is **NEVER** published to relays. It exists solely in the local client memory during the unlocking process.
|
||||
|
||||
### Secret Handling
|
||||
* Secrets (Access Keys) are **never** stored in plain text in IndexedDB or LocalStorage.
|
||||
* Secrets are only decrypted in memory when needed (e.g., to perform an upload or list buckets).
|
||||
* Logging of secret values is strictly prohibited.
|
||||
|
||||
- Secrets (Access Keys) are **never** stored in plain text in IndexedDB or LocalStorage.
|
||||
- Secrets are only decrypted in memory when needed (e.g., to perform an upload or list buckets).
|
||||
- Logging of secret values is strictly prohibited.
|
||||
Reference in new issue
Block a user