Skip to content

Roles and access

Role May
reader Read every resource in their tenant
analyst Change incident status, patch device classification, decide proposals, submit model feedback
responder Create and decide response proposals, release a held action, give response feedback
admin Everything a reader may, plus administrative health detail including host-local messages

Roles are additive and are carried as a sorted, de-duplicated set. Both the dashboard layer and the Go core check the role on every operation, independently — a bug in one layer does not become an authorisation bypass.

From group membership in your OIDC provider. There are no local accounts, and Nyxtrace has no role-editing screen: the authority is your identity provider.

Two kinds of group:

  • An administrator group, granting admin.
  • One group per tenant, granting access to that tenant.

A person with no tenant group has no tenant and sees nothing. That is the intended fail-closed behaviour.

A person in several tenant groups picks one through a server-side session operation before any data route is used. They never hold two tenants at once, and the selection is server-side precisely so that a client cannot choose.

admin is not a tenant. An administrator of the installation does not automatically hold access to a tenant’s data. Memberships are granted explicitly.

analyst cannot execute. Approving a model proposal does not activate the model. Approving a triage proposal does not change a threshold. Approving a classification proposal applies exactly the suggested type and a non-null owner, with an audit trail, and touches nothing else.

responder decides; the executor executes. A response action is a proposal with a rollback plan. Without a response target an approval is a documented decision and nothing more; with one (Pro feature response), the appliance’s worker carries out the approval and the same role may press Release. No role can call a firewall directly.

responder also gives the verdicts. Response feedback — true_positive, false_positive, unknown on an incident — is the responder’s and the admin’s, not the analyst’s, because a false_positive releases every held quarantine of the incident and cancels a pending automatic one. A label that could not release was considered and rejected as a different product; one role that both decides and releases is easier to reason about. The analyst role gets 403, as on a decision or a release.

A non-admin calling the health route gets the same response shape with host-local operational detail redacted from the messages. Not a shorter document, not a different schema, not a 403.

The reason is that a reader still needs to know that a source is stale in order to interpret what they are looking at. Withholding the fact would make the dashboard misleading for them; withholding the host-local string keeps the fact and drops the detail.

Every write records who did it:

  • Incident status changes append to the workflow history with the actor, a comment and a sequence number.
  • Device patches record the classification source, the new confidence and a history entry.
  • Proposal and response decisions record the requester and the approver.
  • Identity merges and splits record an immutable event with the rule, the confidence, the anchors and the actor.

None of it is deletable through the API. An identity split, for instance, does not remove the merge it reverted — it records a reverting event alongside it.