Security
Who is trusted for what. Read this before you integrate the registry or proposals, or before you host a collector.
Longer maintainer write-up: docs/security-model.md on GitHub.
Prove vs Coord (again)
- Prove - the chain re-checks membership, threshold, and signatures. Every write path in registry and proposals does this.
- Coord - an off-chain tool decides "good enough" and the chain trusts it without the same check. Knot's contracts do not work that way.
Do not treat the Lab as the final authorization gate unless the target contract also re-checks on-chain the way Knot does. If some other product trusts a Lab decision without its own check, that product owns the Lab's whole trust surface - say so in that product's docs.
Who holds keys
| Piece | Job | Holds keys? |
|---|---|---|
knot-encoding | Digests and fingerprints | No |
knot-registry | Group storage + quorum checks | No |
knot-proposals | Propose / approve / finalize | No |
knot-tool | Local Lab + CLI | Yes (local only) |
knot-collector | Shared mailbox | No |
On-chain rules (short)
- For ordinary quorum messages, you bind domain + replay protection into the bytes.
- After creating a group, read it back (and the returned id) before wiring it elsewhere.
- Anyone may propose, pass approvals around, or finalize; the signatures are the authorization.
- After quorum, a per-account delay can still hold the action (
Queued/pending) untilexecute/execute_pending. Cancel of that wait is immediate (new quorum), not delayed. - If your contract is called from finalize, require the caller to be the proposals contract.
- Do not propose owner-only admin methods on the proposals contract itself unless that is intentional.
- Treat human-readable proposal summaries as untrusted display text.
Off-chain rules (short)
- The Lab is testnet only - network endpoints are fixed.
- Keys live in the Lab process or a local encrypted store; the browser UI never sees them.
- The Lab listens on loopback; a session cookie (or optional scripting token) protects its API.
- Env password (
KNOT_PWD) only works together withKNOT_ALLOW_ENV_PWD=1. - The Lab also refuses to sign if your local key is not in the live member list - useful UX, but on-chain Prove is still the real guarantee.
- Member public-key order matters for
change_account; shuffle the list and the digest changes. - Treat the collector as hostile; always recompute before sign; put TLS + auth on the reverse proxy.
Integrator checklist
- Put a distinct domain label on every message you pass to
verify_quorum. - Bind replay context (nonce, one-shot state, or both) into that message.
- After
create_account, verify the stored account and returned id before use. - If finalize calls you, check
abi::caller()against the proposals contract id. - Do not trust collector contents or free "verify" HTTP reads for live correctness - recompute locally, then use real writes / account reads.
- Prediction-market council resolve lives in wen (domain
nocturne.wen.prediction-market.council-resolve.v3). Knot does not export those digests.