nool audit verify --framework soc2Who may change what: role-gated grants
Once a replica trusts an issuer (`[governance] issuer_keys`, or the organisation keys in an operator-issued licence), it enforces signed grants held in the DAG. After the first grant lands, a file change needs an `editor` or `planner` grant whose scope covers every path, `nool approve` needs `approver`, `nool steer --role <r>` needs `steer:<r>`, and `nool.toml`, the policy set, plugins and governance packs need `admin`. The seal checks, and so does every replica that pulls. With no issuer configured nothing changes, and `nool doctor` notes `GOVERNANCE_UNDECLARED`.
- Roles: admin, approver, editor, planner, reviewer, coordinator, releaser, auditor, steer:<role> and checker:<assertion>.
- `checker:<assertion>` makes a key a trusted checker for that assertion; it never stands in for human approval.
- `nool login [--hub <url>]` signs in through your identity provider (device flow) and lands short-lived grants mapped from its groups; `nool propose` renews them before they expire.
nool admin team add --id <member-pubkey> --role editor --scope 'src/**'
nool admin team add --id <ci-pubkey> --role checker:unit-tests
nool admin team list
nool admin revoke <grant-id>One organisation, many repositories
A `workspace.toml` above your repositories is the anchor for all of them. `[workspace.governance]` names the organisation and its issuer keys, and `[workspace.policy]` sets the organisation floor: `forbidden_paths` and a minimum completion check. Every repository beneath works under the floor at the seal, at `pre-tool` and in every `nool code` session. A repository can tighten it, never weaken it: a `nool.toml` that asks for less is refused at propose, and `nool doctor` reports `ORG_POLICY_WEAKENED`. The file is honoured only when it belongs to the repository's owner and is not writable by every account.
- At a workspace root, `nool admin team add` signs one grant and lands it in every repository, and `nool admin revoke <key>` revokes every grant of that key.
- `nool workspace doctor --recursive` names repositories whose grants are for another organisation; `nool workspace status --hub` reads the hub's organisation rollup (Enterprise).
# workspace.toml
[workspace.governance]
org_id = "acme"
issuer_keys = ["<hex ed25519 key>"]
[workspace.policy]
forbidden_paths = ["secrets/**", "*.pem"]
[workspace.policy.completion]
red_green = "required"Search across the organisation
`nool query search` searches this repository by default. With a hub configured, `--scope org` searches the hub's index of every repository in the organisation instead. As of 7.24.0 it matches each query term as a prefix and ranks by relevance, so it finds what local search finds: on a labelled set of 25 queries, recall at 5 rose from 0.37 to 0.88. `[hub] search_scope = "org"` makes the organisation the default; an explicit `--scope` always wins.
- If the hub is unreachable, an explicit `--scope org` exits with the hub's error, while a `search_scope = "org"` default falls back to local search with a warning.
- `--fuzzy` is not available with `--scope org`; the hub ranks with Postgres full-text search.
nool query search "webhook retry policy" --scope org --limit 10
# nool.toml
[hub]
search_scope = "org"Configuration changes land alone
A knot that changes `nool.toml` or `workspace.toml` changes nothing else and carries a typed justification, or propose and solidify refuse it with `CONFIG_CHANGE`. A policy pin may land together with the policy files it names. Every governance change is therefore its own reviewable, attributable record.
nool propose --path nool.toml --intent "Require red/green tests" --justification "Q4 quality floor" --solidifyPin the policy set every replica runs
Installing, uninstalling or pinning a policy lands the policy files and `nool.toml` as one knot, so every replica gets the policy with it (`--no-land` keeps the change in the working tree; `nool admin plugin land` lands a rule file written by hand). `nool admin plugin pin` writes every policy file and its hash to `[aram] policies`: once landed, the gate starts only when the policy directory holds exactly that set, and a clone refuses a knot that does not match. `[policy_bundle]` goes further and resolves a signed, content-addressed bundle before evaluation, failing closed when it cannot.
- When the working tree's policies differ from the ones landed at HEAD, the landed set runs as well and its denial stands: moving a policy aside does not let a change through.
- A policy that could not run is recorded Unverifiable, never a pass.
- A policy's manifest is written under the module's own name (plugin `a-b` builds `a_b.wasm`, so `a_b.toml`). Policies with a hyphenated name installed before 7.24.0 could be refused under declared governance: reinstall them.
nool admin plugin install policies/no-secrets.yaml --policy
nool admin plugin pinSigned evidence on every landing
Each governed seal leaves a signed gate receipt on the writer's detached chain with every policy's own result, the policy-set digest, the evidence it read and the lease the seal held. A refused proposal leaves one too, naming the refused payload by hash without its content. Attestations from CI, reviewers and fleets (a fleet's reviewer verdicts are attested as `fleet-review`) replicate with their evidence bodies, so a clone can read them.
nool evidence knot <knot-id>
nool evidence knot <knot-id> --format acsDo the tests constrain the change?
A passing test run proves little if the tests would pass whatever the code did. After a full-mode run passes, `nool propose` re-runs it on a few one-line bugs in the changed lines: a comparison inverted, `&&` and `||` swapped, a boolean flipped, a count off by one, a branch swapped or a return value zeroed. The seal records a `tests_constrain_change` attestation: `pass` when the tests caught every mutant, `fail` with each survivor's file, line and operator, or `error` when nothing could be mutated or the budget ran out. It is never a pass in those cases. Rust, Go, Python, TypeScript and JavaScript are covered.
- With the obligation set and `enforce = "block"`, a push whose tests could not fail is refused, naming the survivors.
- `nool attest show <knot>` and `nool evidence knot <knot>` print a failure's detail.
- This runs at propose on every governed change. `mutation` in `[code.completion]` is the separate check a `nool code` session runs before it declares a goal done.
[reification]
max_mutants = 3 # one ghost run each
mutation_budget_secs = 300
[attestation.obligations]
"src/**" = ["tests_constrain_change"]Working alone: labelled self-approval
A one-person repository has no second person to clear a checkpoint or an approval request, and a second local key posing as a reviewer would fabricate separation of duties. With `[approval] self_approval = "labelled"` landed, `nool approve` and `nool steer` on your own change are recorded instead of refused, carrying a self-approval marker inside the signed payload. Replicas count such a decision only while the setting stays landed, and only for decisions made after it landed. The default, `false`, refuses the author's own decision and drops it on read.
- Turning it on is a `nool.toml` change, so it lands alone with a justification.
- `nool doctor` reports `SELF_APPROVAL_ENABLED` while the setting is landed, with the number of decisions that used it.
- `nool audit verify` records each one as a `self_approved` fact, and a control that requires independent review reports it unmet.
- The signer must still hold the role: a reviewer key, or a grant under declared governance.
[approval]
self_approval = "labelled"How often each gate blocks
Propose and solidify record every gate's verdict against each landing attempt. `nool policy stats` shows, per gate, how often it blocked and how many changes passed it on the first run. `nool doctor` warns `GATE_FIRST_RUN_LOW` when a gate sends most changes back, and `nool insights` and the hub's organisation rollup carry the same counters.
nool policy stats --since 7d
nool policy stats --gate 'policy:*' --jsonProve it afterwards: nool audit verify
`nool audit verify` gives one status per framework control over a range of knots: `PASS`, `FAIL`, `NOT_EVALUATED`, `UNVERIFIABLE`, `NOT_APPLICABLE` or `OUT_OF_SCOPE`. For every knot it re-runs the policy set landed before that knot and reads the reviewer and checker keys from the `nool.toml` landed before it, so an uncommitted edit changes nothing. The verdict comes from git history alone: a fresh clone with Nool's refs fetched reproduces it (`--source git`). Framework packs ship for PCI DSS 4.0.1, SOC 2, the HIPAA Security Rule, GDPR, SOX ITGC and ISO/IEC 27001:2022, and each control names the evidence that satisfies it or says why none can.
nool audit packs --framework pci-dss
nool audit verify --from 7.22.0 --framework soc2
nool audit verify --source git --json --output verdict.jsonRevocation and publication
`nool revocation record|status|export` keeps an append-only, hash-chained ledger of compromise and operational revocations of knots, receipts and signers; offline bundle verification reports whether a signer was revoked at admission or at publication and quarantines revoked publications. `[publication] destination` and destination grants (`nool admin team add --destination <dest>`) bind where a change may land, and gate receipts sign the destination. A server-side pre-receive publication gate verifies the evidence bundle for the exact incoming Git object and refuses quarantined admissions; a short-lived signed break-glass covers one exact ref update.
nool revocation record --class compromise --signer-fingerprint <fp> --effective-at 2026-11-01T09:00:00Z --reason "laptop lost"
nool revocation status --signer-fingerprint <fp>