The EU AI Act inventory, and exports you can prove
Evidence and frameworks
The inventory, the signed pack, and verifying one.
Two things an auditor, a regulator or a customer asks for: a record of the AI in use and how each use has been classified, and evidence that has not been changed since the platform produced it. Both can be sent to them every month.
Uses and the EU AI Act risk class
Under the EU AI Act, the risk class belongs to what a tool is used for, not to the tool. ChatGPT drafting email and ChatGPT shortlisting job applicants are two uses with two classes. So Nyxus records uses: on a tool's page in the AI register, Uses and EU AI Act class > Record a use.
Field | |
|---|---|
What it is used for | the purpose, in a line |
EU AI Act risk class | prohibited, high risk, limited risk, minimal risk, or not classified |
Why this class | the basis for it |
Teams using it | from Settings > Teams |
Owner | who answers for the use |
Human oversight | who checks what it produces, and how |
People affected | job applicants, customers, staff |
Review by | when to look at the classification again |
What each class means, in brief:
Class | |
|---|---|
Prohibited | a practice the Act bans, such as social scoring or recognising emotions at work. The use has to stop |
High risk | a use in an area the Act lists, such as recruiting and managing staff, education, credit or access to essential services. It brings duties such as human oversight and telling the people affected |
Limited risk | people have to be told they are dealing with AI, or that content was made by it |
Minimal risk | no duties beyond the AI literacy everyone using AI at work needs |
Nyxus records your classification; it does not make it. The catalogue's risk tier is about triage, not the Act, and is never copied into a use. If a use is hard to place, ask whoever advises you on the Act.
A tool's page shows the most serious class among its uses. Each company keeps its own uses. Recording, changing and removing a use is in the audit trail.
The inventory
AI register > EU AI Act inventory downloads the inventory over the reporting window: a row for each use of each tool in use, and a row for each tool in use with no use recorded, marked not classified, so a gap shows as a gap.
Format | |
|---|---|
CSV |
|
JSON |
|
Each row carries the tool, its vendor and category, the decision on it and its owner and review date, the use and everything recorded for it, and what was observed: devices, people, personal accounts, first and last seen.
Control mapping
Governance > Frameworks. For five frameworks, each control's identifier beside the evidence Nyxus holds that may support it, and what that evidence says now:
Framework | Identifiers from |
|---|---|
EU AI Act | Regulation (EU) 2024/1689: Articles 4, 5, 6 and Annex III, 26 and 50 |
ISO/IEC 42001 | ISO/IEC 42001:2023: clauses 6.1, 7.5, 8.1, 9.1, 9.3, 10.2, and Annex A.2.2, A.3.2, A.5.2, A.9.2, A.9.4, A.10.3 |
NIST AI RMF | NIST AI 100-1 (AI RMF 1.0): GOVERN 1.1, 1.6, 2.1, 6.1; MAP 1.1, 3.5, 4.1; MANAGE 3.1, 4.1 |
ISO/IEC 27001 | ISO/IEC 27001:2022 Annex A: 5.9, 5.10, 5.15, 5.18, 5.19, 5.23, 5.28, 6.3, 8.12, 8.15, 8.16, 8.19 |
SOC 2 | AICPA Trust Services Criteria (2017): CC2.1, CC3.2, CC4.1, CC6.1, CC6.2, CC6.3, CC6.8, CC7.2, CC7.3, CC9.2 |
The evidence is the records the rest of this page and the portal describe: AI tools in use, uses and their class, decisions, exceptions and rules, personal accounts, paste guard, providers, MCP servers and agents, detection coverage, owners and due dates, campaigns, the access review, the audit trail, signed evidence, events streamed to your SIEM, and the monthly report. Each shows what it holds now in a line, and a gap as a gap: "no destination set", "none sent yet", "1 tool in use with none".
Each framework opens with how many controls are mapped, the kinds of evidence they draw on, and the evidence worth a look: a gap showing now, such as a tool in use with no decision, a source not reporting, or no destination for events. As with the review inputs on the Evidence centre, it says where a person might start, not whether a control works. A dot marks the same evidence in the table.
A suggested mapping, not an assessment. It says where evidence may support a control, in Nyxus's own words. It does not say a control is met, it has no score, and it does not reproduce ISO or AICPA wording: the identifier is there so your auditor can find the control in their own copy and decide what applies.
CSV gives one row per control and piece of evidence, for a statement of applicability or an auditor's workbook. GET /api/controls (framework, fmt=csv, download=true, hours) serves the same thing, and download=true gives the mapping as signed JSON for anyone who wants that document on its own.
Evidence pack is the one to hand an auditor.
The evidence pack
Governance > Frameworks > Evidence pack, or the Export menu on the Evidence centre, which offers a pack for each of the five frameworks. GET /api/evidence-pack?framework=<id> serves it, with an optional hours.
A pack is a zip for one framework, holding only what that framework's controls point at. The EU AI Act's five controls cite five record files; ISO/IEC 27001's twelve cite eight, and a different eight. You are handing over the evidence behind a set of controls, not everything the platform holds.
File | |
|---|---|
| the AI tools in use, their decisions, owners, review dates and providers |
| the EU AI Act inventory: each use, its class, owner and oversight |
| AI used with accounts outside your domains |
| MCP servers configured on devices |
| which detection sources are reporting, against those expected |
| exceptions in force, from the governance file and the portal |
| who can open the company, with which role and why |
| every change and every sign-in, the whole trail rather than one page |
| paste guard activity per tool. Outside |
Check the whole pack with one command. manifest.json carries a checksum of every other file and is itself checksummed and signed, so:
answers for all of it. The mapping and the snapshot inside are the same signed documents their own buttons give, so each still verifies on its own once extracted.
A file that could not be built is named, never dropped. If your role or your deployment cannot produce one - no receiver configured, say - the manifest lists it under unavailable with the reason. A pack quietly missing a file would look complete.
Two packs of the same evidence differ only where the evidence does: every entry is stamped with a fixed date and permissions, so the zip itself adds nothing.
Getting the records out one at a time
Every page a control points at can be exported on its own, for the auditor who asks for one thing rather than a pack:
Page | |
|---|---|
AI register | CSV of the rows on screen, and the EU AI Act inventory as CSV or signed JSON |
Personal accounts |
|
MCP servers |
|
Detection coverage |
|
Paste guard |
|
Exceptions |
|
Audit trail |
|
Accounts |
|
These are convenience exports: the same rows as the page, with when they were taken in the filename, and no manifest. The pack is the evidence artifact.
A team viewer exports none of them, and no pack. Its pages are cut to its team, and a file that leaves the portal carries no cut with it.
Monthly reports
Evidence centre > Monthly report. On the day you choose each month (1 to 28, so every month has it), each company's report is emailed to the recipients you list, through that company's own mail server:
File | |
|---|---|
| the evidence snapshot over the last 30 days, signed |
| the EU AI Act inventory, signed |
| the same inventory for a spreadsheet |
| everyone who can open the company, their role and why, and when any access given ends |
The email's body is a short summary: tools in use and how many are decided, personal accounts, sources reporting, inventory rows by class, and which key signed the files. It lists each file with its checksum.
Monthly is the default; a company only receives a report once it has recipients. Send now builds and sends one straight away. The portal checks every REPORT_CHECK_HOURS (default 6) and sends a due report once that month. One that could not be sent is recorded, with the reason, and tried again the next day. Every report sent, and every failure, is listed on the card and in the audit trail.
The portal builds the evidence snapshot and the inventory and signs them. The receiver builds the access review itself, so the portal's own credential never reads accounts, and sends the email. Sending on a schedule needs the portal's credential (RECEIVER_PORTAL_TOKEN); without it, Send now still works.
Streaming events
Settings > Integrations > Event streaming. Each company sends its audit trail, and every finding if you ask for them, to where your security team already looks: a webhook, Splunk, Microsoft Sentinel or SentinelOne. A company can have several destinations.
What is sent is everything on the audit trail except bookkeeping: decisions, exceptions and rules; AI uses; findings' owners, statuses and tickets; rule matches (rule_matched), broken approvals (approval_broken) and overdue findings (finding_overdue); tools and MCP servers seen for the first time (estate_new) and new things discovery reports; sign-ins, failed sign-ins and break-glass sign-ins; accounts and access; enrollment; companies; reports; settings and upgrades. Every record:
category is one of decision, rule, ai_use, finding, sign_in, account, access, discovery, fleet, company, report, upgrade, budget, settings, or other. Details carry ids, never secrets. With Also send every finding on, each finding stored is sent too, as a record of kind finding.
The receiver sends every EVENT_STREAM_SECONDS (default 30), from the last record each destination accepted: a destination that is down catches up when it is back, and its card says it is failing and why. Delivery is at least once, so use id to discard a repeat. Findings waiting for a destination are held in memory, up to EVENT_FINDINGS_HELD (default 10,000) each, and a restart of the receiver loses those; events are never lost that way. Send a test sends one record of kind test and shows what the destination answered.
Destination | Address | Secret | What arrives |
|---|---|---|---|
Webhook | your https URL | a signing secret, at least 16 characters |
|
Splunk |
| an HTTP Event Collector token | HEC events at |
Microsoft Sentinel | the data collection endpoint, | the client secret of an app registration | rows on your stream through the Logs Ingestion API |
SentinelOne |
| a Write key from Visibility > Log Access Keys | HEC events in the Singularity Data Lake, sourcetype |
Checking a webhook
Each request carries X-Nyxus-Timestamp and X-Nyxus-Signature: sha256=<hex>, an HMAC-SHA256 with your secret over the timestamp, a full stop, and the body as sent. Recompute it, compare in constant time, and refuse a timestamp more than a few minutes old.
Setting up Microsoft Sentinel
In the Log Analytics workspace behind Sentinel, create a custom table, for example
NyxusEvents_CL, with columnsTimeGenerated(datetime),Kind(string),Category(string),Company(string),EventId(string) andDetail(dynamic).Create a data collection endpoint, and a data collection rule with a stream
Custom-NyxusEventsof those columns, sending to the table.Register an app in Entra, create a client secret, and give it the Monitoring Metrics Publisher role on the data collection rule.
Add the destination with the endpoint, the tenant and client ids, the secret, the rule's immutable id (
dcr-...) and the stream name.
Read API
Settings > Account > API tokens. A token lets another system, such as a reporting tool, read what a viewer can see, and change nothing. It is for one company, or for every company, until a date you choose. An owner of the company makes it; a token for every company needs an owner of the hosting company. The token is shown once, when it is made, and only a hash of it is kept. The card shows when each was last used. Making and revoking a token is on the audit trail.
Send it to the portal on GET requests, and name the company:
Without X-Nyxus-Company a token reads its own company, or the hosting company for a token for every company. A company the token does not cover is refused, never swapped for another. Anything other than GET is refused.
Path | |
|---|---|
| the AI register: each tool in use, its decision, its uses and their class. |
| the EU AI Act inventory, signed |
| the evidence snapshot, signed |
| the audit trail, newest first, |
| who can open the company, their role and why |
| the companies the token covers |
| the control mapping. |
| one framework's evidence as a signed zip. |
| the public keys exports are signed with |
A revoked token, one past its date, or one used for a company it does not cover gets a 401 that says so.
Signed exports
A checksum shows a file was not damaged, but anybody who edits a file can compute a new one. A signature needs the deployment's private key. Evidence snapshots and the JSON inventory are signed when the portal has a signing key:
The signature covers the whole document except the signature itself, serialised with sorted keys and no incidental whitespace. The document's checksum leaves the signature out, so it still holds. An unsigned export has "signature": null.
The key
The key is a 32-byte Ed25519 seed held as a secret beside the portal's own token. It is never in the receiver's database: an account that could read it through the admin API could sign documents of its own.
Route | Where the key comes from |
|---|---|
Helm | generated by the chart and kept across upgrades ( |
Compose |
|
System health > Report signing shows the key id and the public key. A key that cannot be read costs signatures, not the portal: exports carry "signature": null and System health says signing is not set.
To replace a key, set the new seed and list the old public key in REPORT_SIGNING_PREVIOUS_KEYS (portal.reportSigning.previousKeys), so reports signed with it can still be checked against a key the deployment publishes. GET /api/signing-keys returns both.
Checking a file
Exit | |
|---|---|
0 | the checksum matches and the signature is valid (and by the key you named) |
1 | the document was changed, or its signature is not valid |
2 | the file could not be read |
3 | validly signed, but by a key other than the one you named |
Without --key it says which key signed the document; compare that with System health. nyxusctl verify needs no third-party package: checking a signature touches only public data.