← Standards alignment

Recommended alignment · NIST SP 800-207 · Zero Trust Architecture

How we recommend aligning your private AI with NIST SP 800-207.

The Zero Trust standard sets out seven tenets. For each one, here's what it requires, the approach we recommend, the configuration that implements it, and how you confirm it's working. This is a recommended reference — the exact configs are finalized against your deployment.

Source: NIST SP 800-207, Zero Trust Architecture ↗ · tenets paraphrased; read the original for the authoritative text.

How to read this. "Requirement" is our plain-language reading of the tenet — not a quote. "Configuration" is the recommended recipe on an OpenZiti + local-model appliance; yours may differ. Nothing here claims certification.
All 7 tenets · complete

Tenet 1Requirement
All data sources and computing services are treated as resources — each protected in its own right, not lumped into one trusted zone.
What we recommend
Define each capability as its own Ziti service with its own policy — the model endpoint, each document store, each tool — so every resource is individually addressed and individually governed. There is no flat "inside the network is trusted" zone.
The configuration
# Each capability is a separate governed resource, not one flat zone
ziti edge create service private-ai   --configs ai-host,ai-intercept
ziti edge create service docs-index   --configs docs-host,docs-intercept
ziti edge create service tool-runner  --configs tool-host,tool-intercept
See it work
$ ziti edge list services
private-ai    # the model endpoint
docs-index    # the document store
tool-runner   # any tool the AI may call
# each resource is addressed and policed on its own
Tenet 2Requirement
All communication is secured regardless of network location — being "on the LAN" grants no trust.
What we recommend
Publish the AI as a dark service on an OpenZiti overlay: it binds only to localhost, has no listening port on the LAN, and is reached only through a mutually-authenticated (mTLS) Ziti session. Nothing on the office network can see it.
The configuration
# Bind the model to localhost only; expose it as a dark Ziti service
ziti edge create config ai-host host.v1 \
  '{"protocol":"tcp","address":"127.0.0.1","port":8899}'
ziti edge create config ai-intercept intercept.v1 \
  '{"protocols":["tcp"],"addresses":["private-ai.ziti"],
    "portRanges":[{"low":80,"high":80}]}'
ziti edge create service private-ai --configs ai-host,ai-intercept
See it work
$ nmap -Pn appliance.local
All 1000 scanned ports are filtered   # nothing listens on the LAN
# reachable only as private-ai.ziti, over mTLS, by an enrolled identity
Tenet 3Requirement
Access to each resource is granted per session — reaching one resource never implies access to another.
What we recommend
Lean on Ziti's per-session model: every connection is authorized against that resource's own dial policy at connect time. A live session to the model carries no authorization toward the document store — each is granted, and re-checked, on its own.
The configuration
# Each resource has its own dial policy — granting one never grants another
ziti edge create service-policy docs-dial Dial \
  --service-roles '@docs-index' --identity-roles '#staff-legal'
# a session to 'private-ai' is not a session to 'docs-index'
See it work
$ ziti edge list sessions
identity=jdoe  service=private-ai   # this resource only
# jdoe reaching docs-index is authorized separately, against docs-dial
Tenet 4Requirement
Access is decided by dynamic policy — identity, the service, and the requesting device's posture — not a static allow-list.
What we recommend
Attach posture checks to the dial policy — require MFA and a managed, up-to-date OS — so a device gets a route only while it meets the posture, and loses it the moment it doesn't. Being enrolled isn't enough on its own.
The configuration
# Require MFA + a healthy OS before the dial policy grants a route
ziti edge create posture-check require-mfa MFA
ziti edge create posture-check managed-os OS --os 'macOS:>=14'
ziti edge update service-policy ai-dial \
  --posture-check-roles '@require-mfa,@managed-os'
See it work
$ ziti edge list posture-checks
require-mfa  MFA
managed-os   OS   macOS >= 14
# a device with no MFA, or on an old OS, gets no route — even if enrolled
Tenet 5Requirement
The integrity and security posture of all assets is monitored and measured — continuously, not just at first connect.
What we recommend
Keep posture checks continuous — Ziti re-evaluates them during a session and drops access if a device falls out of compliance — and protect the appliance's own integrity, so the AI can't disable its own controls.
The configuration
# Posture is re-checked during the session (Ziti drops access on drift).
# Appliance self-integrity — the agent cannot alter its own controls:
guardrails:
  config_self_protection: true   # its config is read-only to the agent
  reality_check: true            # post-turn verification stays on
See it work
$ hermes doctor
posture monitoring ......... ON   # drops access on MFA/OS drift
config self-protection ..... ON
reality-check .............. ON
Tenet 6Requirement
All authentication and authorization are dynamic and strictly enforced before access is allowed.
What we recommend
Grant access with explicit Bind/Dial service-policies — nothing is reachable by default. Only the appliance identity may serve the model; only enrolled staff devices may reach it, each authenticated per session.
The configuration
# Who may serve it, and who may reach it — deny-by-default
ziti edge create service-policy ai-bind Bind \
  --service-roles '@private-ai' --identity-roles '@ai-appliance'
ziti edge create service-policy ai-dial Dial \
  --service-roles '@private-ai' --identity-roles '#staff'
See it work
$ ziti edge list service-policies
ai-bind  Bind  @private-ai  @ai-appliance
ai-dial  Dial  @private-ai  #staff
# a device with no enrolled identity in #staff gets no route at all
Tenet 7Requirement
Collect as much information as possible about access and system state, and use it to improve security posture.
What we recommend
Turn on the local audit log so every access and action is recorded in plain English — kept on the appliance, never sent out — giving you the record this tenet expects (and the evidence an auditor asks for).
The configuration
# Record every access & action to a local, plain-English log
audit:
  enabled: true
  path: /var/hermes/audit.log        # stays on the appliance
  fields: [time, identity, action, target, decision, policy]
See it work
2026-07-29 14:22:01  identity=jdoe  action=read
   target=/matters/acme/contract.pdf  decision=ALLOW  policy=reader

All seven tenets of NIST SP 800-207, each with the requirement, the approach we recommend, the configuration that implements it, and how you confirm it's working. This is standard 1 of the alignment set — where 800-207 governs who can connect, standard 2 governs what the AI may do: NIST AI RMF →

Want this run against your setup?

The free Readiness Check tells you which of these you already meet and which need work — then the build puts the recommended configuration in place.

Start the free Readiness Check →