Security Model
Where keys live
The seed phrase and all derived private keys exist in exactly two states:
- Encrypted at rest in
bundler/out/vault.json— PBKDF2 key derivation + AES-128-CTR + keccak MAC. - In memory while the vault is unlocked in a running engine process.
They are never sent to the website, never logged, never committed. out/ is git-ignored.
The seed phrase
Shown exactly once at generation, with an explicit write-it-on-paper warning. It is not stored in plaintext and cannot be re-displayed. If you lose both the phrase and the vault password, the wallets are gone.
Unlock model
The vault stays locked until you POST /api/unlock with the password. Every signing path (funding execution, launch, buys, sells) checks the unlocked state and refuses otherwise — the API answers coffre ferme instead of failing halfway through a transaction.
Execute flags
Read-only endpoints simulate; they never broadcast. Anything that moves ETH requires an explicit execute: true in the request body and an unlocked vault. launchAndBuy additionally runs an eth_call simulation before sending — if the simulation reverts, nothing is broadcast.
Blast radius
- Server binds
127.0.0.1— nothing on the network can reach it. - The app page and the engine are same-origin; the API has no auth token because it never leaves localhost. Do not expose the port.
- Wallet-0 funding is the only hot key with meaningful ETH during setup; the bundle wallets hold only their distribution share until launch.
What you should still do
- Write the seed on paper. Not a screenshot, not a password manager note — paper.
- Keep the vault password distinct from anything else.
- Lock the vault (restart the engine) when you step away.