Skip to article
← Back to knowledge base

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

/api/ai-inventory?fmt=csv for a spreadsheet. A cell that a spreadsheet would run as a formula is kept as text

JSON

/api/ai-inventory?fmt=json, with inventory_sha256 over the document and, where the deployment has a signing key, a signature

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.

nyxus-evidence-pack-eu-ai-act-2026-09-18T0021Z.zip
├── manifest.json          signed, with a sha256 of every file below
├── control-mapping.json   the signed mapping, scoped to this framework
├── control-mapping.csv    the same mapping as a spreadsheet
├── evidence.json          the signed evidence snapshot for the same window
└── records/               the record files these controls cite

File


records/ai-register.csv

the AI tools in use, their decisions, owners, review dates and providers

records/ai-inventory.csv

the EU AI Act inventory: each use, its class, owner and oversight

records/personal-accounts.csv

AI used with accounts outside your domains

records/mcp-servers.csv

MCP servers configured on devices

records/coverage.csv

which detection sources are reporting, against those expected

records/exceptions.csv

exceptions in force, from the governance file and the portal

records/access-review.csv

who can open the company, with which role and why

records/audit-trail.csv

every change and every sign-in, the whole trail rather than one page

paste-guard-by-tool.csv

paste guard activity per tool. Outside records/ because it is per tool and never per event - metadata only, and the content that tripped a detector is not in it

Check the whole pack with one command. manifest.json carries a checksum of every other file and is itself checksummed and signed, so:

nyxusctl verify manifest.json

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

GET /api/personal-accounts.csv

MCP servers

GET /api/mcp-servers.csv

Detection coverage

GET /api/coverage.csv

Paste guard

GET /api/paste-guard.csv, per tool and metadata only

Exceptions

GET /api/exceptions.csv

Audit trail

GET /api/audit?fmt=csv, the whole trail rather than the page

Accounts

GET /api/users?fmt=csv, the access review for this company

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


evidence.json

the evidence snapshot over the last 30 days, signed

ai-inventory.json

the EU AI Act inventory, signed

ai-inventory.csv

the same inventory for a spreadsheet

access-review.csv

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:

{"id": "default:4182", "at": "2026-09-14T10:02:11+00:00", "kind": "decision_recorded",
 "category": "decision", "company": "default", "detail": {"tool": "claude", "status": "approved", "by": "gengar"},
 "source": "nyxus"}

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

POST of {"source": "nyxus", "events": [...]}

Splunk

https://<host>:8088

an HTTP Event Collector token

HEC events at /services/collector/event, sourcetype nyxus:event or nyxus:finding

Microsoft Sentinel

the data collection endpoint, https://<endpoint>.ingest.monitor.azure.com

the client secret of an app registration

rows on your stream through the Logs Ingestion API

SentinelOne

https://ingest.<region>.sentinelone.net

a Write key from Visibility > Log Access Keys

HEC events in the Singularity Data Lake, sourcetype nyxus:event or nyxus:finding

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.

expected = hmac.new(secret, timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest("sha256=" + expected, signature)

Setting up Microsoft Sentinel

  1. In the Log Analytics workspace behind Sentinel, create a custom table, for example NyxusEvents_CL, with columns TimeGenerated (datetime), Kind (string), Category (string), Company (string), EventId (string) and Detail (dynamic).

  2. Create a data collection endpoint, and a data collection rule with a stream Custom-NyxusEvents of those columns, sending to the table.

  3. Register an app in Entra, create a client secret, and give it the Monitoring Metrics Publisher role on the data collection rule.

  4. 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:

curl -H "Authorization: Bearer nyxr_..." -H "X-Nyxus-Company: co_1a2b3c4d" \
     "https://nyxus-portal.example.com/api/ai-inventory?fmt=json"

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


GET /api/register

the AI register: each tool in use, its decision, its uses and their class. hours

GET /api/ai-inventory?fmt=json

the EU AI Act inventory, signed

GET /api/evidence

the evidence snapshot, signed

GET /api/audit

the audit trail, newest first, limit at a time (at most 1,000). Pass the response's next_before as before for the next page

GET /api/users

who can open the company, their role and why

GET /api/companies

the companies the token covers

GET /api/controls

the control mapping. framework, fmt=csv, download=true for the signed JSON

GET /api/evidence-pack

one framework's evidence as a signed zip. framework is required, hours optional

GET /api/signing-keys

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:

"signature": {
  "alg": "Ed25519",
  "key_id": "nyx-3f2a9c0d41be7e55",
  "public_key": "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=",
  "scope": "document_without_signature",
  "value": "..."
}

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 (portal.reportSigning). Name your own Secret with portal.reportSigning.existingSecret

Compose

openssl rand -base64 32 > secrets/report_signing_key, read as REPORT_SIGNING_KEY_FILE

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

nyxusctl verify nyxus-evidence-2026-09-14T1200Z-168h.json --key <public key from System health

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.

© 2026 Aman Karir