sudoX · access

Who can do what

A credential carries a role and an organisation. The role decides which verbs are available; the organisation decides which records they apply to. Neither can be widened by asking nicely.

Four roles

Every credential is one of four. They are cumulative — each adds to the one before it — and the whole authorisation model is a single table in the code, so what is written below is what runs.

RoleCanCannot
viewerRead everything their organisation holds: incidents, plans, findings, policies, the audit trail.Change any of it. Not a setting, not a service, not a resolution.
responderWork an incident. Run an analysis, draft a plan, dry-run it, resolve an incident, assign one.Approve a plan or execute one — including their own.
approverAuthorise and run. Approve a plan, execute it, decide a knowledge proposal.Manage credentials, policies or connections.
adminEverything above, plus the platform itself: tokens, the approval policy, the AI connection, alert routing, the emit policy, cost settings, environments, what is watched.Reach another organisation, or lower the two floors below.
A responder can draft a plan and cannot approve it. That is the separation the whole gate depends on: the person proposing a change to production is not the person who says yes to it.

A role inside an environment

A credential can be assigned a role within a named environment — an approver in staging who is a viewer in production. Two rules make that safe, and both are the same rule the agent mode follows.

An assignment can only narrow, never widen. A credential issued as a responder cannot be made an approver by assigning it one in an environment: the organisation role is the ceiling, and a surface that could raise it would be a way to grant approval rights without issuing a credential that has them.

No assignments means the organisation role applies everywhere. Not "no access". An upgrade must not take an approver's rights away in every environment because nobody has assigned them yet — and the gateway secret and an SSO session have no token behind them at all. Restriction is something an operator opts into, per credential, and the console says which credentials have.

The check happens at the approval gate, with the plan in hand: approving a plan that touches production requires the approver's role in production. A plan touching several environments needs all of them. Rejecting is never gated — refusing to run something stays open to anyone who can see it.

Try it

Pick a credential, pick an action, read the verdict.

Every request the console makes is checked by one table: the verb it needs, the role the credential has, and — for approvals — the role it has in each environment the plan touches. The check is the same one the API runs, so the sentence below is the one the audit trail would record.

the check

the api says

in the console Access (roles, assignments, issuing) · Audit (refused requests are recorded too) · pkg/identity

What to notice. A responder cannot approve, and no assignment makes them able to: set "in prod" to approver and the verdict does not move, because the organisation role is the ceiling. Make the credential an approver and assign it viewer in prod: now it can approve a plan in staging and not one in prod, and a plan touching both is refused for the one environment that falls short. Rejecting is open to anyone who can see the plan, in every case. And a record in another organisation is not refused — it is not found, which is the only answer that does not confirm it exists.

Two floors no role reaches

The approval policy decides what may run with nobody in the room. An admin can make almost anything autonomous. Two rules are not reachable from it at all, by any role, under any policy.

A destructive step always needs two different people. Delete, drop, terminate — whatever a rule says. And "different" is counted by credential, not by display name.

A write with no rollback step always needs a human. If the plan cannot say how to undo it, nobody is asleep while it runs.

These are stated in the policy editor as well, above the rules rather than below them — an operator who writes an autonomy rule for a destructive step and then watches it not work should have read why beforehand. Try the gate.

An organisation is a boundary, not a filter

A credential belongs to exactly one organisation, and a record belonging to another answers not found rather than forbidden. That distinction is deliberate: a boundary that says "forbidden" has confirmed the thing on the other side exists, which is half of what the asker wanted to know.

A tenant admin is an admin of their tenant. They cannot mint a credential in another organisation, read its audit trail, or see what its agent is allowed to do unattended.

What an organisation covers — and what it does not

Most of a single-tenant deployment never meets this. It matters when a deployment holds more than one organisation: almost everything is scoped, and the few parts that are one per deployment are listed below. The full list is docs/tenancy.md.

Per organisationMeaning
credentialsTokens, roles, environment assignments, and who issued them.
audit trailEvery state-changing request, refused ones included — and every unattended execution and scheduled verification, with the environment named.
approval policyWhat may run without a human, matchable on environment.
AI connectionProvider, credential and enable switch — so each tenant's agent authenticates as, and is billed as, itself.
task modelsWhich model runs each of the agent's tasks.
alert routingSlack, email, Teams and the rest — where a page lands, matchable on environment.
emit policyWhich alerts are held back, and the record of what was held.
connectionsCloud accounts and databases, every credential sealed.
environmentsThe names for parts of the estate, and each one's agent mode.
watchingWhich derived sources and signals an operator switched on or off.
cost settingsThe billing export a cost report reads, and the last bill read.
runtime modeTraining, shadow or detect.
action plansWhat somebody intends to change, and the commands that would do it.
findingsOpen problems in the estate and their remediation.
runbooksWhat the agent reads back when it plans a fix.
incidents and analysesAn alert belongs to the organisation of the credential that sent it; repeated detections fold into one incident per organisation.
baselinesLearned from the organisation's own sources, and read only by its own analyses and conversations.
service healthThe heatmap's snapshots and collection timing, built from the organisation's own sources, patterns and incidents.
conversationsChat sessions, the record of what was asked, and which toolsets the chat is offered.
reportsSettings, content, schedule and sending.
Deployment-wideWhy
the learned-signal catalogLog patterns, the agent's judgements and the service list are one store fed by every source the worker polls. Only the platform organisation reads it; to any other it answers not found, and a tenant's own screens are built from its own records instead.
the deployment's own sources and KubernetesThe sources in the configuration files and the Kubernetes connector read with the deployment's own credentials, so their tools serve the platform organisation alone and refuse a tenant.
agent promptsThere is one of each agent in the process, so an edited system prompt is what every organisation's agent is told. The citation check and the gates are code, not prompt.
the runbook search indexRunbooks are filed per organisation; the index the agent searches is built over all of them.
applied connectionsStoring is per organisation; applying to the running process is deployment-wide, so what the server has live is the default organisation's set. The console says which it is.
learn exclusionsThey hold a service or pattern out of that same catalog. A per-tenant exclusion would be a control the console could express and the learner could never apply, which is worse than a shared one.
teams and on-callThe roster is a property of the deployment's people, not of a tenant.
A stated limit beats a silent one. Where a control is per organisation, its console page says whose settings you are reading and whether another organisation holds its own — so an empty policy is never mistaken for the deployment having none.

How an alert gets its organisation

The alert intake needs a credential carrying ingest. Every role has it, and the integration role has nothing else, so a sender such as Alertmanager can be given a token that can send alerts and do nothing more. An alert belongs to that token's organisation, and is held, routed and recorded under it. Each organisation is held to a ceiling of alerts a minute.

A deployment can choose the old open intake (intake.open): then an alert with no credential is accepted under the default organisation, and the process says so in its boot log.

The one credential that crosses

The gateway secret in the deployment's configuration is the owner's root credential. It is an admin in every organisation and reads the audit trail across all of them.

That is not a gap. It predates every organisation and can already mint an admin token inside any of them, so hiding anything from it would be theatre rather than a boundary. What it can be is retired: issue named admin credentials, and the secret stops being the thing anybody reaches for — which also means the audit trail starts naming people instead of naming "gateway secret".

← Inside sudoX Environments →