Sentinel-Witness / README.md
Lawless1987's picture
Add model-card front-matter (license/tags/title)
83006bc verified
|
Raw History Blame Contribute Delete
8.13 kB
---
license: apache-2.0
pretty_name: Sentinel-Witness
tags:
- trading
- dashboard
- ledger
- crypto
---
# Ledger Trading Dashboard
Phone-first PWA: Ledger hardware wallet + Coinbase/Kraken/Crypto.com, staged
dashboard β†’ manual-approval β†’ automated execution, driven by walk-forward-
validated grid/bracket strategy parameters (see the companion `strategy/`
Python project) with a real-time adaptive layer on top.
## What's actually tested vs. what needs your device
This was built in a sandboxed environment with no access to Coinbase/
Kraken/Crypto.com's APIs, no WebHID, no real Ledger. That shaped what
"tested" can honestly mean here:
| Module | Tested | How |
|---|---|---|
| `secureStorage.js` | Yes | Full encrypt/decrypt round trip, wrong-passphrase-fails-closed, fresh salt/IV per save β€” real IndexedDB via `fake-indexeddb`, not mocked |
| `gridMath.js` | Yes | Lookahead safety, capital-safety invariant, parity against the Python engine's validated $12 dead-weight case, throttle-never-hits-zero |
| `exchanges/kraken.js`, `cryptocom.js` signing | Yes | Determinism, structural correctness (output length/format), key-order invariance |
| `exchanges/coinbase.js` JWT | Partially | ES256 JWT structure and signature cryptographically verified against a generated key pair β€” confirms the *mechanism* is right. Does **not** confirm a real Coinbase CDP key imports cleanly; that needs your actual key |
| `tradeGate.js` tier enforcement | Yes | Every limit-rejection path, tier-gating path, and the "no unlimited option" guarantee, via a mock exchange |
| `ledger.js` | No β€” cannot be | Needs a real browser (WebHID) and a real device |
| Live exchange calls (balances, order placement) | No β€” cannot be | This sandbox's network can't reach any of the three exchanges |
| UI (`Dashboard.jsx`, `App.jsx`) | No β€” cannot be | Needs a real browser |
Run `npm test` to re-run everything that *can* run outside a browser.
## Setup
```
npm install
npm run dev # local dev server
npm run build # production build, output in dist/
```
### Exchange credentials
- **Kraken**: create an API key with Query Funds + Create/Cancel orders
permissions (not Withdraw). Enter the key + secret in the app; they're
encrypted with your passphrase and stored only in this browser's
IndexedDB.
- **Crypto.com**: same shape (API key + secret), trading permissions only.
- **Coinbase**: create a CDP API key (Advanced Trade). The downloaded
private key must be PKCS8 PEM (`-----BEGIN PRIVATE KEY-----`). If yours
says `-----BEGIN EC PRIVATE KEY-----`, convert it first:
`openssl pkcs8 -topk8 -nocrypt -in your-key.pem -out converted.pem`
None of these should ever have withdrawal permission. This app only ever
needs to read balances and place/cancel limit orders.
## Security model
- **Ledger**: signing happens on-device with a physical confirmation.
This code never sees a seed phrase or private key β€” see `ledger.js`'s
docstring. WebHID (required for the Ledger connection) works in Chrome/
Edge on desktop and Android; it does **not** work in any iOS browser,
including Safari-based ones on iPhone. On iOS, this needs a native app
with Ledger's Bluetooth SDK instead β€” flagged, not built here.
- **Exchange credentials**: AES-GCM encrypted with a key derived from
your passphrase (PBKDF2, 210k iterations), stored in this browser's
IndexedDB. This is real protection against someone reading files off
disk. It is **not** equivalent to a native app's OS Keychain/Keystore β€”
a PWA can't reach either. See `secureStorage.js` and the in-app
`SecurityNotice` component.
- **Trade execution guardrails**: all enforced in `tradeGate.js`, not
just documented β€” automated tier refuses to start without finite,
positive `maxPerTradeUsd` and `maxDailyTradesCount` (no unlimited
option), both re-checked on every signal, not just at setup. Every
execution path requires the Ledger confirmation step; there is no
code path that skips it.
## What's genuinely not built yet
- **XRP unsigned-transaction-blob assembly.** `tradeGate.executeApprovedSignal()`
gets all the way to calling the Ledger and reading the address, then
throws an explicit `not_implemented` error rather than faking a
completed trade. Turning a `{pair, price, quantity}` signal into the
actual bytes `signXrpTransaction()` needs to sign (proper XRP Ledger
transaction encoding, sequence numbers, fees, submission to a node)
is real protocol work not done in this pass β€” flagged loudly rather
than stubbed quietly, per this whole project's standing rule about
silent failures being the dangerous kind.
- PWA icons (`icon-192.png`, `icon-512.png` referenced in `vite.config.js`)
aren't generated.
- Only XRP is wired through the UI/gate end-to-end; the strategy guide
covers DOGE too (see `src/lib/strategyGuide.js`) but the app only
asks for one asset right now.
## Automated-tier setup
`AutomatedSetupModal.jsx` replaced the earlier `prompt()`/`alert()`
placeholder. Real form, real inline validation (mirrors
`tradeGate.js`'s own `enableAutomated()` check exactly β€” see
`src/lib/automatedLimits.js` β€” so the UI never blocks something the gate
would allow or vice versa), and a live "worst-case daily deployment"
figure (`maxPerTradeUsd Γ— maxDailyTradesCount`, related to current USD
balance when known) so the two numbers you're locking in mean something
concrete before you confirm, not just two blank fields. Covered by
`src/lib/__tests__/automatedLimits.test.js`.
While wiring this in, found and fixed a second bug: the "Dashboard" tier
button rendered clickable while at manual/automated tier (stepping down
is deliberately always open, from any tier β€” see `tierNavigation.js`),
but `handleTierChange` had no branch for it, so tapping it silently did
nothing. Confirmed empirically before fixing (not assumed), and now
covered by `src/lib/__tests__/tierNavigation.test.js`, which asserts the
dashboard-tier case directly rather than just the fields it happened to
break in.
## Re-generating the strategy guide
`src/lib/strategyGuide.js` embeds a snapshot from
`recursive_strategy_optimizer.py` (the Python walk-forward optimizer, in
the companion `strategy/` project β€” re-run that periodically, it's
designed for it). Either replace the `BAKED_IN_GUIDE` constant with fresh
output, or host the JSON somewhere and call `refreshGuide(url)` so the
app picks up updates without a rebuild.
---
## Part of one system β€” each piece usable on its own
These repositories are independent instruments that also compose into a single apparatus for **building and honestly auditing trustworthy multi-intelligence systems**. Any one can be used standalone; together they form the stack:
- **Governed core** β€” [covenant](https://huggingface.co/Lawless1987/covenant): a self-governing multi-agent system with an ethics gate inside the transaction path.
- **Observability & provenance** β€” [threefold](https://huggingface.co/Lawless1987/threefold) (the L-lens layer over Jacobian Lens) and [threefold-memory](https://huggingface.co/Lawless1987/threefold-memory) (its persistent, provenance-tracked memory): every action measured and recorded under one task identity.
- **Measurement instruments** β€” [contradiction-probe](https://huggingface.co/Lawless1987/contradiction-probe) and [flinch-observability](https://huggingface.co/Lawless1987/flinch-observability), with the session records [flinch-record](https://huggingface.co/Lawless1987/flinch-record) and [grokflinch](https://huggingface.co/Lawless1987/grokflinch): preregistered, blind-scored tests of AI behaviour that embody the covenant's rule β€” *investigate a signal, never convict on one*.
- **Neuromorphic research** β€” [spiking-experiments](https://huggingface.co/Lawless1987/spiking-experiments): from-scratch spiking-network experiments with the pass/fail bar declared before each run.
- **Ledger surface** β€” [Sentinel-Witness](https://huggingface.co/Lawless1987/Sentinel-Witness): the trading / ledger dashboard.
**This repository's place in it:** the ledger / trading-dashboard surface.