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
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 cannot execute either — in this version. A response action is a proposal with a rollback plan, and execution is a separate module.

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.