Compliance readiness, attestations and history
The compliance dashboards (Enterprise plan) show, per framework, which controls your organization meets and how. This page explains how each control's status is decided.
How a control's status is decided
Every control is in one of four states:
- Satisfied — at least one audit entry in the period counts toward it. An entry counts if the act succeeded, or if the act is a refusal (a refused agent action, a denied approval): a control refusing something is evidence it works. A request that was itself refused, such as an agent registration over your plan's cap, does not count.
- Attested — a person has signed that the control is met by means Zynth cannot see (below). Shown apart from satisfied, never as satisfied.
- Not applicable — a control that asks about a population you do not have (no agents, no agent that talks to people, no high-risk agent, no serious incident). Left out of the score.
- Gap — none of the above, with how it closes: in the platform (some act in Zynth evidences it) or attest (nothing in Zynth can).
Readiness is (satisfied + attested) over the controls that apply.
Controls judged from your registers
Six controls ask for something about every AI system, not for an activity, and are judged from your AI-governance registers as they stand today:
| Control | Satisfied when |
|---|---|
| EU AI Act Art 26 | every agent has an inventory profile |
| EU AI Act Art 27, ISO/IEC 42001 8.4 | every agent has a current approved impact assessment that is not past its review date |
| EU AI Act Art 50 | every agent that talks to people has an interaction disclosure in force |
| EU AI Act Art 15 | every high-risk agent has a passing evaluation from the last 90 days |
| EU AI Act Art 73 | every serious incident's report was filed by its due date |
A gap says how many are missing ("2 of 5 agents lack it"). These controls cannot be attested.
Expect readiness to drop when this version reaches you. Refused acts no longer count, and the register-backed controls now ask about every agent rather than finding one record. The new number is the honest one.
Attesting a control
Some controls are met outside the platform: AI literacy training (EU AI Act Art 4), the absence of
a prohibited practice, data governance done elsewhere. A person with compliance:admin can attest
one:
- a statement of how it is met, an owner (an active member), evidence links, and a review date after today and within the next year, both judged by the UTC date (in Singapore, before 08:00 the UTC date is still yesterday's, and the console's date picker follows it);
- it counts as attested until its review date; after that it lapses and the gap shows again;
- one attestation is in force per control; attesting again replaces it, which is how you renew one before it lapses (the console offers Renew… on an attested control, and the control stays attested throughout); revoking it keeps the record and shows the gap;
- only people attest or revoke, never an agent or an API key, and the statement's text is kept on the attestation, not copied into the audit log.
A reported prompt injection from your SDK (prompt_injection_suspected) is the evidence for the
OWASP goal-hijack control (ASI01). Any member who can report SDK signals can file one, so treat
that control's status as "your integration reports these", not as an independent finding.
curl -X POST "$ZYNTH/api/v1/command/compliance/attestations" -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -d '{
"control_id": "EU_AI_Art4",
"statement": "Every person operating our AI systems completed AI literacy training in 2026.",
"owner_id": "<a member user id>",
"evidence_refs": [{"label": "Training register", "uri": "https://lms.example.com/ai-101"}],
"review_due_on": "2027-03-31"}'
Readiness over time
Zynth records each framework's readiness once a day, with every control's status, so you can show
where you stood on a given date and when a gap opened. GET /api/v1/command/compliance/history
returns the daily records for a framework over up to a year.
Exporting evidence for an auditor
GET /api/v1/command/compliance/evidence?framework=…&export=true returns the evidence pack with a
manifest: the SHA-256 of the pack and the audit chain's last verification. The same digest is
recorded in your audit log with the export (command.evidence_generated), so a file handed to an
auditor can be matched to the export that produced it. To check a file, remove manifest and hash
the rest exactly as Python serialises it, which is the canonical form:
import hashlib, json
pack = json.load(open("evidence.json"))
pack.pop("manifest")
text = json.dumps(pack, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
print(hashlib.sha256(text.encode("ascii")).hexdigest()) # equals manifest.digest
The console's Export button saves the response exactly as the server sent it, so its file
checks as above. Other JSON tools (jq, JavaScript) format numbers and non-ASCII text differently
and will not reproduce the digest, so never save the pack through one: a 1.0 re-written as 1
is enough to fail the check.
Identifiers
The OWASP agentic controls follow the published OWASP Top 10 for Agentic Applications 2026
(OWASP26_ASI01 … OWASP26_ASI10), and the ISO/IEC 42001 controls use the standard's clause
titles. Evidence recorded under an older identifier counts toward the control it now names.
In the console
Compliance → a framework (Enterprise) shows readiness over the period you choose (30 days to a year),
each control's status and how a gap closes, and, for a gap only an attestation can close, an
Attest button for holders of compliance:admin. Below it: readiness over time, the attestations
recorded (in force, lapsed or revoked, with who and why, and Revoke), and the evidence with an
Export that shows the manifest's digest once downloaded.