fix: complete v5 routing — API exposure, rescore persistence, leverage cap, key backup doc
Three plumbing fixes + one ops doc that close the gaps from the audit. scripts/rescore_v5.py Was overwriting only signal/conf/reasoning/sentiment/relevant/ prefilter_reason/analysis_version. Now also persists target_asset, category, expected_move_pct — without these the bot can't route rescored posts correctly (would silently fall back to BTC). app/schemas.py + app/api/posts.py TrumpPost response model didn't expose target_asset/category/ expected_move_pct, so the frontend had no way to display "this signal will trade SOL". Added the three fields + mapping in _post_to_schema(). Pre-v5 posts return null. No frontend changes yet — display work is a follow-up. app/services/hyperliquid.py HL caps max leverage per asset (BTC/ETH 50×, SOL 20×, memes 3-5×). set_leverage() always tried to push self._leverage — if user set 30× and bot routed to TRUMP, HL rejected the order and the trade silently dropped. Added _get_max_leverage() (queries meta()'s maxLeverage field) and _clip_leverage() that caps to HL's max. set_leverage now returns the effective leverage so callers can use it for notional sizing if needed. deploy/ENCRYPTION_KEY_BACKUP.md Documented mandatory backup procedure for the symmetric key that encrypts every user's HL API key. Lost key = all users' bots dead with no recovery. Includes rotation procedure + quarterly test step + things-not-to-do list. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# ENCRYPTION_KEY backup procedure — DO NOT SKIP
|
||||
|
||||
The `ENCRYPTION_KEY` env var encrypts every user's Hyperliquid API key
|
||||
before it touches the database. If this key is **lost** or **rotated
|
||||
without re-encrypting** the existing rows, every active user's bot
|
||||
permanently stops trading — there is no recovery path. This is the
|
||||
single most-load-bearing secret in the project.
|
||||
|
||||
## What it looks like
|
||||
|
||||
```
|
||||
ENCRYPTION_KEY=1cf813d6790cc1b1c0981951703ca387d58321d81dc9b5b4982c07487edc478e
|
||||
```
|
||||
|
||||
A 64-char hex string (32 bytes). Used by `app/services/crypto.py` via
|
||||
Fernet-equivalent symmetric encryption.
|
||||
|
||||
## Backup requirements (mandatory before going live)
|
||||
|
||||
Store the production value in **at least two locations**, at least one
|
||||
of which is **offline / non-cloud**:
|
||||
|
||||
### 1. Password manager (1Password / Bitwarden / KeePass)
|
||||
- Item type: "Secure Note"
|
||||
- Title: `TrumpSignal — ENCRYPTION_KEY (production)`
|
||||
- Body: the 64-char hex value
|
||||
- Add note: "Lost = every user's bot dead. No way to recover."
|
||||
- Tag/folder for fast retrieval
|
||||
|
||||
### 2. Offline physical backup
|
||||
Pick one (or do both):
|
||||
- **Paper**: print the key on a single sheet, store in a locked drawer
|
||||
/ safe / safety deposit box. Label: "TrumpSignal encryption key —
|
||||
do not discard, do not photograph, do not type into computers."
|
||||
- **Hardware key**: write to a USB drive that lives offline, kept in
|
||||
the same safe. Label and date it.
|
||||
|
||||
### 3. (Optional) Co-founder / trusted-party split
|
||||
If multiple humans run the project: split the key (Shamir's Secret
|
||||
Sharing or just give halves to two people) so no single person can
|
||||
walk off with it AND no single person can lose all copies.
|
||||
|
||||
## Before any rotation
|
||||
|
||||
Rotating the key is **not free**. To rotate:
|
||||
|
||||
1. Generate `NEW_KEY`.
|
||||
2. **Decrypt every existing `subscriptions.hl_api_key` with the old
|
||||
key**, re-encrypt with the new key, write back. (Script not
|
||||
shipped — has to be written carefully.)
|
||||
3. Only after the migration completes, swap env var and restart.
|
||||
4. Update both backup locations with `NEW_KEY`.
|
||||
5. Securely destroy the old key copies after a 30-day cool-off
|
||||
(during which you confirm no users got broken).
|
||||
|
||||
If you skip step 2, every existing user's HL key becomes garbage on
|
||||
the new server and their bot silently stops working.
|
||||
|
||||
## How to test backups (do this once a quarter)
|
||||
|
||||
1. Pull the key out of password manager → match against the env var
|
||||
on the running server.
|
||||
2. Pull the offline copy → match against the password-manager copy.
|
||||
3. Confirm both match. If any drift, sync immediately — never assume
|
||||
the running server has the "true" copy without verifying.
|
||||
|
||||
## What NOT to do
|
||||
|
||||
- ❌ Don't paste the key into Slack / Discord / email.
|
||||
- ❌ Don't commit the key to git (`.env` is in `.gitignore`, but
|
||||
double-check before any `git add -A`).
|
||||
- ❌ Don't share via screenshot — keys can be OCR'd from anywhere.
|
||||
- ❌ Don't store only on the server — if the server dies, you lose it.
|
||||
- ❌ Don't rotate "just because" — it's expensive and risky.
|
||||
Reference in New Issue
Block a user