fix: require client secrets and sanitize uploaded images
This commit is contained in:
1 parent
1f43b2d065
commit
a07c178fda
7 files changed
+78
-24
No files matched your search
@@ -10,7 +10,7 @@ Provide a small single-host service that routes image-generation requests from i
|
||||
|
||||
- Photobooth/installation clients submit a prompt, model, optional parameters, and zero or more images.
|
||||
- An administrator provisions clients and manages access.
|
||||
- A client may manage its own upstream keys when it has a client secret.
|
||||
- Every client must have a secret. Generation, job polling, and client-managed key operations require that secret.
|
||||
- The initial service runs as one Uvicorn process against a local SQLite database on persistent disk.
|
||||
|
||||
## Requirements
|
||||
@@ -31,7 +31,7 @@ Provide a small single-host service that routes image-generation requests from i
|
||||
### Non-functional and security
|
||||
|
||||
- Use async HTTP for all upstream network I/O and a shared bounded connection pool.
|
||||
- Bound aggregate uploaded bytes and image count. Allow only configured raster image MIME types.
|
||||
- Bound aggregate uploaded bytes, image count, and decoded pixel dimensions. Accept only valid JPEG, PNG, and WebP images; re-encode before forwarding to strip metadata and trailing payloads.
|
||||
- Require an explicit administrator secret at startup; never ship a default secret.
|
||||
- Store client secrets hashed. Store provider keys only because they are needed for upstream requests; restrict database file access and redact keys from API responses.
|
||||
- Scope job reads and client key operations to the authenticated owning client.
|
||||
@@ -51,7 +51,7 @@ Provide a small single-host service that routes image-generation requests from i
|
||||
- `provider` (optional: `google` or `openrouter`)
|
||||
- `params` (optional JSON object string)
|
||||
- `images` (repeated image upload fields)
|
||||
- `x-client-secret` header when a secret is configured for that client
|
||||
- `x-client-secret` header (required)
|
||||
|
||||
Success is `200` with `provider_used`, `model_used`, `images`, `text`, elapsed time, and failover attempt count. With `?async_mode=true`, success is `200` with `job_id`, status, and poll URL.
|
||||
|
||||
@@ -69,7 +69,7 @@ Validation errors use FastAPI's `detail` format; upstream failures return `502`
|
||||
|
||||
## Data model
|
||||
|
||||
- `clients`: client ID primary key, name, optional client-secret hash, activation flag, creation timestamp.
|
||||
- `clients`: client ID primary key, name, required client-secret hash, activation flag, creation timestamp.
|
||||
- `provider_keys`: owned by a client with cascading deletion; provider constrained to `google`/`openrouter`; key, priority, activation and failure metadata.
|
||||
- `jobs`: owned by a client with cascading deletion; status, serialized request/result/error and timestamps. On startup, interrupted jobs are marked failed.
|
||||
|
||||
@@ -78,7 +78,7 @@ SQLite connections enable foreign keys and busy timeout; WAL is initialized once
|
||||
## Architecture and flow
|
||||
|
||||
1. FastAPI validates the multipart request and client authentication.
|
||||
2. Uploaded images are bounded and encoded for the provider's JSON API.
|
||||
2. Uploaded images are bounded, decoded, re-encoded to an allowlisted raster format, then encoded for the provider's JSON API.
|
||||
3. A route loads the active client's provider keys from SQLite.
|
||||
4. The adapter translates the request to Google or OpenRouter format and sends through shared async `httpx`.
|
||||
5. A retryable upstream failure advances to the next configured key; success is normalized into a provider-neutral response.
|
||||
@@ -88,7 +88,7 @@ SQLite connections enable foreign keys and busy timeout; WAL is initialized once
|
||||
|
||||
1. Install Python dependencies and set a unique `ADMIN_SECRET`.
|
||||
2. Mount a persistent local volume at the configured database path with restrictive permissions.
|
||||
3. Run one Uvicorn worker. Put TLS and request-size enforcement at Nginx; keep port 8000 private.
|
||||
3. Run one Uvicorn worker as `www-data`, bound to `127.0.0.1:8081`. Put TLS and request-size enforcement at Nginx; keep the application port private.
|
||||
4. Create clients, add provider credentials, then call `/healthz` and verify one small generation using the intended account/model.
|
||||
5. Back up the database securely. Treat backups and job records as secrets and apply retention appropriate to the installation.
|
||||
|
||||
|
||||
Reference in new issue
Block a user