guard.rs

crates/veilvoice-cli/src/guard.rs

veilvoice-cli · 359 lines · read the source here · or on GitHub

veilvoice guard -- record what VeilVoice's files should be, and check them.

Detection, not prevention. See veilvoice_guard::SCOPE, which every path through this module prints, for the same reason the app lock prints its own: a protection someone over-trusts has made them less safe, not more.

What the three steps actually do

  • init walks the files that make up this installation and records a SHA-256 for each. Optionally sealed with a passphrase, so the record itself cannot be quietly rewritten to match tampered files.
  • check re-walks and reports what is modified, removed and added. All three matter: an added file in the installation directory is as interesting as a changed one.
  • blame tries to say which process made a change, and says plainly when it cannot.

Why attribution usually fails, and why that is reported rather than hidden

Attribution needs the operating system to have been recording. On Linux that means an auditd watch; on Windows a SACL on the path plus the audit policy enabled, and reading it needs elevation. Neither is on by default on a normal machine.

So the common answer is "something changed this file and I cannot tell you what", and this module prints exactly that rather than an empty list. An empty list reads as nothing happened, which is the opposite of the truth, and is the same mistake as a monitor reporting an empty machine because a registry query silently matched nothing.

The bound, again

A manifest running as the user protects nothing from that user, and detects rather than prevents even when it works. Anything that can write these files can write the manifest beside them. That is why the passphrase-sealed record exists, why veilvoice_guard::SCOPE is printed on every path through this module, and why the word "tamper-proof" appears nowhere in it.

In plain words

Writes down what VeilVoice's own files should look like, and checks later that they still do.

It notices changes. It does not prevent them, and every path through it says so, because a check somebody believes is a lock is worse than no check.

WHAT THIS FILE CONTAINS

359 lines defining 9 functions (1 public), 1 type and 0 constants. Everything below is read out of the source, so it cannot disagree with the code.

The types it owns.

  • enum Action line 54

What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.

  • run line 117 · Dispatch veilvoice guard to the subcommand that was asked for.
    reaches check, init, manifest_path, status, load, print_scope, sealed_path, default_targets

WHAT CALLS WHAT

manifest_path line 75 sealed_path line 88 print_scope line 94 default_targets line 103 run line 117 init line 134 load line 197 check line 214 status line 284 entry: a way in: public, and nothing in this file calls it helper: private to this file dashed: a call that goes back up, or across a wrapped rank The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

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_manifest_path["manifest_path<br/>line 75"]
    n_sealed_path["sealed_path<br/>line 88"]
    n_print_scope["print_scope<br/>line 94"]
    n_default_targets["default_targets<br/>line 103"]
    n_run(["run<br/>line 117"])
    n_init["init<br/>line 134"]
    n_load["load<br/>line 197"]
    n_check["check<br/>line 214"]
    n_status["status<br/>line 284"]
    n_check --> n_load
    n_check --> n_print_scope
    n_check --> n_sealed_path
    n_init --> n_default_targets
    n_init --> n_print_scope
    n_init --> n_sealed_path
    n_load --> n_sealed_path
    n_run --> n_check
    n_run --> n_init
    n_run --> n_manifest_path
    n_run --> n_status
    n_status --> n_print_scope
    n_status --> n_sealed_path
    click n_manifest_path href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L75" "open the source"
    click n_sealed_path href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L88" "open the source"
    click n_print_scope href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L94" "open the source"
    click n_default_targets href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L103" "open the source"
    click n_run href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L117" "open the source"
    click n_init href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L134" "open the source"
    click n_load href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L197" "open the source"
    click n_check href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L214" "open the source"
    click n_status href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-cli/src/guard.rs#L284" "open the source"
    classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    class n_run entry
    classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
    class n_manifest_path,n_sealed_path,n_print_scope,n_default_targets,n_init,n_load,n_check,n_status helper

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.

ITEMS

ItemLineDocumentation
Action pub enum54
manifest_path fn75Where the manifest lives, beside the app lock.
sealed_path fn88A sealed manifest sits beside the plain one, with a different suffix.
print_scope fn94Say what the integrity record detects and what it cannot, before it is used.
default_targets fn103The files worth watching when the user names none: the running binary, and the app lock beside it.
run pub fn117Dispatch veilvoice guard to the subcommand that was asked for.
init fn134veilvoice guard init: record what these files are now.
load fn197Load whichever form of the record exists, asking for a passphrase only if the sealed one is the one that is there.
check fn214veilvoice guard check: compare the files against the record and report.
status fn284veilvoice guard status: what the record covers, and when it was taken.