Magistrala
Dev Guide

Authorization

Magistrala's authorization model — Atom's Permission Blocks, Roles, and Direct Policies, and how Magistrala services (including Enterprise ones) check access against Atom.

SpiceDB is gone — authorization now runs through Atom

No SpiceDB container exists in docker-compose.yaml, and the old per-entity relations/permissions schema and REST role management API (/<entity_type>/<entity_id>/roles) no longer apply. Authorization is now owned entirely by Atom — see Auth.

The model

Atom answers one question: can subject S perform action A on object O?

Subject gets a Role.
Role contains Permission Blocks.
Direct Policy gives a Subject one Permission Block directly.
Permission Block is the only place where scope and actions are defined.
TermMeaning
SubjectThe entity or principal group receiving access — in Magistrala terms, a User, Device, or Gateway.
ActionAn operation name such as read, write, publish, manage. Atom seeds 13 common ones; tenants can add more.
Action ApplicabilityA valid action/object-kind-and-type pairing (e.g. publish is applicable to resource:channel) — governs which actions are even selectable for a given object.
Permission BlockScope + actions + effect (allow/deny) + optional ABAC conditions. The only place access is actually defined.
RoleA friendly name bundling one or more Permission Blocks, assignable to subjects.
Direct PolicyGives one Permission Block directly to one subject — narrower and more auditable than a full role.
Assignment GuardrailAn assignment-time rule blocking/allowing a given action from being granted to a given entity kind at all.
Principal GroupA who-container — members inherit role assignments made to the group.
Object GroupA where-container — permission blocks can target everything inside it.

Every new tenant (Workspace) gets a seeded tenant-admin role with the full administrative permission set — the successor to the old built-in admin role.

Decision flow

Deny-by-default, deny-overrides-allow:

  1. Load the subject and the object being acted on.
  2. Resolve the action and validate it's applicable to that object kind/type.
  3. Collect the subject's role assignments and direct policies (expanding principal group membership).
  4. Evaluate every matching Permission Block.
  5. Any matching denyDeny, full stop, regardless of any allow.
  6. Otherwise, any matching allowAllow.
  7. No match at all → Deny (the default).

Permission Block shape

This is what Magistrala's Go code sends/receives:

type PermissionBlock struct {
	ID         string
	TenantID   string
	ScopeMode  string
	ObjectKind string // e.g. "entity", "resource", "group", "tenant", "role", "policy"
	ObjectType string // namespaced, e.g. "resource:rule", "resource:invoice"
	ObjectID   string // set only for an exact-object scope
	GroupID    string // set only for group-scoped modes
	Effect     string // "allow" or "deny"
	Conditions map[string]any // ABAC, {} for unconditional
	Actions    []Capability
}

ScopeMode is one of nine values: the tenant itself; all objects of a kind; all objects of a type; one exact object (by ObjectKind/ObjectType/ObjectID); an object group itself; direct objects in a group; objects in subgroups; direct child groups; or descendant groups.

DirectPolicy (one Permission Block → one subject) and GroupGrant (one Permission Block → every member of a principal group, present and future) are the two ways a block actually reaches a subject without going through a named Role — both also transcribed directly from pkg/atom/types.go.

How Magistrala services check authorization

Every service that needs an authorization decision — including the Enterprise alarms, reports, and re (Rules Engine) services — asks Atom the same shape of question Magistrala's own Go types describe:

type AuthzRequest struct {
	SubjectID  string
	Action     string
	ResourceID string
	ObjectKind string
	ObjectID   string
	Context    map[string]any
}

type AuthzResponse struct {
	Allowed bool
	Reason  string
}

The Enterprise services observed use ObjectKind = "resource" with a namespaced ObjectType like resource:rule — consistent with Atom's generic object-kind model above, not a bespoke per-service schema. The publicly-runnable equivalent is the CLI:

magistrala-cli authz check <subject_id> <action> --object-kind <kind> --object-id <id> --token <token>

(see the Authz CLI — the only authorization-related CLI command; there is no CLI for managing Roles/Permission Blocks/Direct Policies themselves, which are administered through Atom directly.)

Atom's action set is tenant-configurable rather than a fixed compiled schema the way SpiceDB's was, so this page doesn't maintain a static action catalog table — it would go stale. Use Atom's own Actions and Effective Actions views to see what's actually granted right now.

On this page