veilvoice-policy
Settings that can only be tightened, sealed with the project's own post-quantum cryptography.
reference · the same page on GitHub
Settings somebody else decided, sealed so they cannot be edited without a passphrase, and, more importantly, built so that editing them without one buys nothing worth having.
The design decision this crate turns on
A policy file has an obvious problem. To apply a policy at every launch, the program has to be able to read it at every launch. If reading it needs a passphrase, the user types one every time, and if it does not, then anybody who can write the file can rewrite the policy.
The usual answers are a privileged daemon holding the key, or a key hidden in the binary, and neither is honest here: this project needs no privileges, and a key in a binary anybody can download is not a key.
So the constraint is moved into the shape of the data. A requirement can only make VeilVoice stricter. There is no requirement that turns encryption off, none that lowers the de-identification floor, none that disables the app lock, and there is no room in Requirement to express one, because every variant is a tightening and the type has no other kind.
Then somebody who edits the plain policy file without the passphrase can do exactly one thing: make this machine's VeilVoice more restrictive than its owner asked for. That is a nuisance, and it is not a privacy failure: which is the failure this project exists to avoid. The passphrase-sealed copy is what proves the policy is the one the administrator wrote; the shape of the type is what makes the answer survive the seal not having been checked yet.
What the seal is for, and what it is not
Policy::seal uses the same container as everything else here: Argon2id over the passphrase, X25519 with ML-KEM-768 for the hybrid modes, XChaCha20-Poly1305 for the contents. verify opens the sealed copy and compares it against the plain one, which is how anybody with the passphrase establishes that the policy in force is the policy that was written.
It is not enforcement. Anything with write access to VeilVoice's own executable can replace VeilVoice, and no file it reads can prevent that. Anything running as the user can delete the policy entirely. What a sealed policy gives is a policy that cannot be quietly rewritten into something weaker, and that is a smaller claim than "enforced" on purpose. See SCOPE.
Detecting deletion is veilvoice-guard's job, not this one's: put the policy files in a tamper manifest and the removal shows up there.
Reading a policy costs nothing
Policy::load reads the plain file and applies it. It never asks for a passphrase, never blocks, and reports the seal as Verification::Unchecked rather than pretending to have looked. A front end that wants the stronger statement calls verify when it has a passphrase to offer.
In plain words
This lets settings be locked down, and only in one direction.
Someone setting up a machine for other people can seal a set of settings so they can be made stricter but never looser. Nobody needs a password to read what the rules are -- only to change them -- because a rule people cannot see is a rule they will trip over.
HOW THE CRATE FITS TOGETHER
Every arrow is a crate:: or super:: path one module actually uses, read out of the source rather than drawn by hand.
The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
n_lib(["lib.rs<br/>168 lines"])
n_mandate["mandate.rs<br/>539 lines"]
n_policy["policy.rs<br/>984 lines"]
n_workspace["workspace.rs<br/>817 lines"]
click n_lib href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-policy/src/lib.rs" "open the source"
click n_mandate href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-policy/src/mandate.rs" "open the source"
click n_policy href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-policy/src/policy.rs" "open the source"
click n_workspace href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-policy/src/workspace.rs" "open the source"
This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.
THE FILES
| File | Lines | What it is |
|---|---|---|
lib.rs | 168 | Settings somebody else decided, sealed so they cannot be edited without a passphrase, and, more importantly, built so that editing them without one buys nothing worth having. |
mandate.rs | 539 | The two things VeilVoice insists on unless you say otherwise. |
policy.rs | 984 | The policy itself: what can be required, and what requiring it does. |
workspace.rs | 817 | Named profiles and saved projects. |