30-second answer
One executable, m365-governance, with thirteen subcommands. They split into
three jobs: reaching a tenant and writing down what was seen, deciding what the
evidence means, and handing the result to somebody who does not have this
engine.
The thirteen commands
m365-governance [-h] [--version]
{list-rules,show-rule,collect,explain,doctor,stats,validate,
evaluate,assess,verify,report,diff,contracts}| Command | What it does |
|---|---|
collect | Run a collector against a tenant and write evidence. Evaluates nothing |
stats | What a collector managed to see, before evaluating it |
evaluate | Run rules against an evidence document |
assess | Evaluate evidence and write an assessment that can be handed over |
explain | What an outcome means, and what it does not |
report | Re-render a stored report, without evaluating anything |
diff | What changed between two assessments, and what it does not say |
list-rules | Every rule, with the kind of claim it makes |
show-rule | One rule in full, including what it does not establish |
validate | Check every rule against the schemas and the invariants |
doctor | What is wrong with this installation, before you ask |
verify | Check an assessment that arrived, without the engine that made it |
contracts | Write the contract bundle a consumer vendors |
What holds across all of them
Collection never writes. A collector has no write path to the tenant. When collection fails, the failure message says so explicitly, because the first question anybody asks about a failed run against production is what it left behind.
Rules come from the installed version unless you say otherwise. Every
command that reads rules takes --rules, and the help text is precise about
what that does: supplying a directory replaces the packaged rules entirely
rather than adding to them.
Exit codes carry meaning. 0 succeeded. 2 means the engine refused: an
argument was missing, a document was not what the command expects, or the
inputs would have produced a claim the evidence does not support. 1 means the
command ran and the result was negative: rules failed under --fail-on, an
assessment did not verify, doctor found something wrong, or collection
failed. See exit codes.
Nothing reads the clock except where it must. assess takes
--created-at, so the same inputs rebuild the same bytes. An assessment whose
digest moved because time passed would be unverifiable by construction.
The path through them
collect -> stats -> evaluate -> assess -> diff
|
v
verifycollect reaches the tenant. stats says what it managed to see before you
read any conclusion. evaluate produces a report for you. assess produces a
document for somebody else, and verify is what that somebody else runs.