Authorization
The single policy decision point Scrydon uses for every authorisation check — Rego-backed, multi-tenant, audited.
Every authorisation check in Scrydon flows through a single policy decision point (PDP). One model, evaluated the same way regardless of whether the caller is a user, a workflow, or a service-to-service request.
The four-step pattern
Every protected operation follows this pattern:
- Build the authorisation context — actor, organisation, workspace, requested action, resource type.
- Resolve the resource — look up the target row (the workflow, the knowledge-base document, the managed-table row).
- Evaluate the policy registry — the registry holds typed policies, one per resource kind, and dispatches to the right one.
- Mark the request as evaluated — without this marker, downstream layers fail-closed. There is no path that returns "allow" without explicit evaluation.
This four-step contract is enforced at the type system level: routes that don't follow it fail static analysis.
Where Rego fits
For data-plane reads (managed-table rows, projected ontology objects), the policy decision point is Open Policy Agent. Each tenant has a compiled Rego bundle that encodes:
- Data classifications — which columns are confidential / restricted / public.
- Mask strategies — which roles see which columns, redacted, hashed, or denied.
- Row filters — predicates that restrict which rows a given role can see.
When a workflow reads a managed table, the query is evaluated by OPA against the caller's identity. Rows that fail the filter are excluded; columns that fail the mask strategy are redacted before the value leaves the data-plane service.
OPA is the default and expected deployment path. A fallback in-process policy engine is also supported for environments where running an OPA sidecar isn't operationally desirable. Both paths consume the same policy bundle.
Multi-tenancy boundary
Authorisation is always scoped to an organisation. There is no way for a workflow in one organisation to read or write data in another organisation, regardless of the user's role. This boundary is enforced at three layers:
- Database — every table that holds tenant data has a
organizationIdcolumn and a foreign-key constraint to the organisations table. Cross-org joins are not possible. - Application — every API route builds the authorisation context from the session's
organizationId. There is no "switch organisation" call that mutates the active org without re-authenticating. - Data plane — Rego policies are compiled per organisation. A bundle compiled for org A cannot evaluate a request for org B.
Execution grants
Workflow executions don't carry user identity through the payload. Instead, the API route that triggers the workflow evaluates the user's permission, then issues a short-lived execution grant stored server-side. The workflow runtime receives only a grant reference plus the business input.
This prevents two attack classes:
- A copied workflow payload cannot be replayed against a different workflow instance with the same authority.
- A tool activity cannot expand beyond the parent workflow's tenant scope, because the grant is bound to a single workflow instance.
Secret access is delegated as a separate short-lived sub-grant. A workflow's authority does not implicitly grant secret reads; each secret read requires its own grant.
Grant creation, binding, rejection, expiry, and revocation are all recorded in the audit log.
Related
- Permission model — the three-tier hierarchy that feeds into the policy decision point.
- Audit logging — every authorisation evaluation is auditable.
- Architecture → Analytics stack — where Rego data-plane policies are applied.
- SPIFFE / mTLS — service-to-service authentication that underpins service callers.