Signing that a leaked laptop can't drain.
Keys in an .env file are how treasuries disappear. We put signing behind a policy: hard limits, an allowlist, and an approval quorum, with the key itself living in a KMS or HSM where it can't be read out. Every signature is checked before it's made, and logged after.
Flip the request to over-limit. The same guard that signs the good one refuses the bad one at the policy stage, before a key is ever touched.
Where the key lives decides everything.
A private key in an .env file is one leaked laptop from an empty treasury. In an HSM it can't be read out at all. Switch the store and try to take the key.
The HSM produces signatures on request but never releases the key material. Reading it out simply isn't an operation the hardware offers.
Policy, written down and enforced.
The rules aren't in someone's head. They're a file you can read, review, and change, and the signer refuses anything that breaks them.
1# signing-policy.toml2[limits]3per_tx = "20 ETH"4daily = "50 ETH"56[recipients]7mode = "allowlist" # deny by default8allow = ["treasury-ops", "payroll", "market-ops"]910[approvals]11quorum = 2 # of 3 signers12window = "10m"1314[keys]15backend = "kms" # key lives in the HSM16export = false # can never be read outNo single transaction over 20 ETH, no more than 50 in a day. Enforced before signing.
Only named recipients can receive. A new address is refused until it's added.
Every signature needs a quorum, collected inside a short window or it expires.
The key backend is set so the raw key can never leave the vault, not even for you.
Every signature, accounted for.
When money moves, you can say exactly what happened, who approved it, and whether policy allowed it. The log is append-only, so it can't be quietly rewritten after the fact.
Signing that a leaked laptop can't drain.
Hard limits, an allowlist, and an approval quorum, with the key itself living in a KMS or HSM where it can't be read out. Every signature checked before it's made, and logged after.