The suite
Six plugins, six refusals.
They install together and are enabled together. Each one owns a single decision and says no in one specific way.
| Plugin | Decides | Refuses with | Platform |
|---|---|---|---|
| keyvault | Whether a signature or decryption may happen at all | MRD-01xx | macOS / Linux |
| network | Whether a socket may open, and through which route | MRD-02xx | macOS / Linux |
| e2e | Whether a message body may leave in readable form | MRD-03xx | macOS / Linux |
| llm_guard | Whether a prompt may reach a remote model | MRD-014x | macOS / Linux |
| privacy_check | Nothing — it only reports what the others decided | n/a · exit code | macOS / Linux |
| wizard | Whether the configuration is complete enough to run | MRD-09xx | macOS / Linux |
[TBD]Reason-code ranges and per-platform differences to be confirmed by engineering.
mordred_keyvault
Holds the identity.
Signing and decryption are requested, never performed in your process — the private key stays behind the platform helper for its whole life.
- MACOS
- Secure Enclave · P-256
- LINUX
- TPM 2.0 · persistent handle
It refuses
- Any request to export, print, or back up key material. MRD-0101
- Signing when the hardware attestation does not match the policy. MRD-0107
mordred_network
Egress is denied by default.
A run inherits exactly one declared route — Tor, a VPN, or clearnet — and cannot widen it while running.
- ROUTES
- tor / vpn / clearnet
- DEFAULT
- deny
It refuses
- Connections to hosts outside the declared allow-list. MRD-0204
- Falling back to a weaker route when the declared one is down. MRD-0201
mordred_e2e
Seals message bodies to the recipient before the transport client sees them.
Slack, Discord, and mail relays carry ciphertext and metadata, nothing more.
- GATEWAYS
- slack / discord / smtp
- SEAL
- age · recipient key
It refuses
- Sending to a recipient with no known public key. MRD-0302
- Plaintext delivery, even when the gateway asks for it. MRD-0305
mordred_llm_guard
The last check before a prompt leaves for a remote model.
A match halts the call rather than redacting quietly, because a silent edit hides the real problem.
- SCANS
- keys, tokens, private paths
- LOGS
- match name, never value
It refuses
- Prompts carrying credentials or key material. MRD-0142
- Providers with no guard profile configured. MRD-0148
mordred_privacy_check
Reads the live configuration rather than the file you meant to write.
It decides nothing; it just makes the current state legible, and exits non-zero when a guarantee is unmet.
- OUTPUT
- one line per guarantee
- EXIT
- 0 met · 1 unmet
mordred_wizard
Guided setup for the other five.
It either leaves you in a state the policy can enforce, or stops and tells you which answer is missing.
- WRITES
- ~/.mordred/policy.toml
- IDEMPOTENT
- re-run any time
It refuses
- Finishing with an undeclared route or a missing key. MRD-0902
- Writing a policy weaker than the one already on disk without --downgrade. MRD-0911
How they compose.
One outbound message passes each decision in order. A refusal anywhere in the chain stops the whole run — there is no partial send.
- Agent writes a message
- llm_guard scans for secrets
- e2e seals the body
- network opens the declared route
- Slack receives ciphertext
keyvault signs and decrypts underneath all four; the key never appears in the chain.
privacy_check reads the chain afterwards and reports which links held.