# What this install tells an assessor

> The NIST SP 800-171r3 control document and audit report — what each covers and who can read them.

Source: /toft-docs/latest/admin/security/compliance/

**Admin → Compliance** produces two documents against **NIST SP 800-171
Revision 3**, from one registry compiled into the binary.

> **Caution**
>
> This is audit **support**: it makes an assessment cheaper to run. It is not an
> attestation and not evidence that one was passed.

## Two documents

| | **Control document** | **Audit report** |
|---|---|---|
| Describes | the **build** — what Toft does per requirement | the **install** — what this machine is set to now |
| Reads | nothing | settings, providers, credentials, sources, apps |
| Stale when | you upgrade | you change anything |
| Download | PDF, `toft-800-171r3-controls-<version>.pdf` | JSON export, `compliance-<install>-<date>.json` |

Both render the same registry, so they cannot disagree about what the controls
are. The PDF is generated in the binary, so it works without outbound HTTPS, and
every page footer names the build.

## Responsibility

Each of the 97 requirements is one of:

| | |
|---|---|
| **platform** | Toft does this |
| **shared** | Toft does part; you do the rest |
| **inherited** | Your infrastructure does it |
| **customer** | Entirely yours |

At least twenty stay *customer* or *inherited* — a test holds that floor. There is
**no score**: nineteen requirements have nothing to do with Toft, so an average
would mean nothing.

## Parameters bound to settings

Where SP 800-171 asks you to define a value, the report reads your live setting:

| Parameter | Setting |
|---|---|
| Account inactivity period | `dormant_lock_days` |
| Session termination period | `session_idle_minutes` |
| Malware response | `dependency_block_malware` |

Parameters the install does not hold are shown as **unbound** and counted.

## Evidence outcomes

All 39 evidence items always produce a row:

| | |
|---|---|
| `ok` | Read; here is the value |
| `absent` | The install does not offer that capability — not a finding |
| `refused` | An access boundary stopped the read |
| `error` | It should have worked and did not |

A bare install produces no `error` rows.

## The export

The report is computed per request and never stored. The JSON export names the
install, the date and the collector, and carries a **digest recomputable from the
file alone** (it covers its own timestamp). File it wherever you keep evidence.

The digest is the SHA-256 of the `report` member in [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) canonical JSON, and the file says so in `sha256_rule`. Any RFC 8785 library recomputes it. So does Python's standard library, since these documents use plain keys and whole numbers:

```sh
python3 -c 'import json,sys,hashlib; d=json.load(open(sys.argv[1])); b=json.dumps(d["report"],sort_keys=True,separators=(",",":"),ensure_ascii=False); print(hashlib.sha256(b.encode()).hexdigest()==d["sha256"])' export.json
```

It prints `True` for an unaltered file.

## One app's audit file

Each app also has an **Audit** tab, read by its editors. It shows the app's own evidence: grants, with who gave each one and when; deploys and who started them; packages and an SBOM per release; reach; credential age; logs; viewers; and deletion. Each section is checked exactly as the page it mirrors would be. An editor who is not an administrator sees the app's change history as **Refused**, with the reason, and never sees more than they could elsewhere. A personal API key can read it; deploy keys cannot.

| | API |
|---|---|
| The reading the tab shows | `GET /api/v1/apps/{id}/audit-file` |
| The export, with its digest | `GET /api/v1/apps/{id}/audit-file/export` |
| One release's SBOM | `GET /api/v1/apps/{id}/deployments/{deploymentID}/sbom` |

Only the export carries a digest, a `sha256` beside the `report` member under the same rule as this report's, and the command above checks it too. The reading is the live page and has none.

It lists access. Reviewing that access is the organization's job, not Toft's.

## Who can read it

**Administrators in a browser only.** All five routes return 404 to
non-administrators and refuse every API key class, deploy keys included.
[Scan targets](/toft-docs/latest/admin/security/scan-targets.md) is the deliberate contrast: a deploy key can read
addresses, not posture.

Not license-gated — a lapsed install can still read its own posture.

Out of scope: other frameworks, POA&M, remediation tracking, per-app compliance,
scheduled generation, attestation.
