Documentation
¶
Index ¶
- Constants
- Variables
- func CalculateSubScopes(scope Scope) []string
- func Denied(scope Scope, selector Selector) error
- func GrantsToContext(ctx context.Context, grants []Grant) context.Context
- func InvalidCheck(scope Scope, resourceID string) error
- func ResourceKindForScope(scope Scope) string
- func SeedSystemRoleGrants(ctx context.Context, logger *slog.Logger, db *pgxpool.Pool, ...) error
- func SyncGrants(ctx context.Context, logger *slog.Logger, db *pgxpool.Pool, orgID string, ...) error
- func ValidateSelector(scope Scope, sel Selector) error
- type ChallengeLoggingEnabled
- type Check
- type DeniedError
- type Engine
- func (e *Engine) Filter(ctx context.Context, checks []Check) ([]string, error)
- func (e *Engine) GetScopeOverrides(ctx context.Context) ([]RoleGrant, bool)
- func (e *Engine) InvalidateAllRoleCaches(ctx context.Context, orgID string)
- func (e *Engine) InvalidateRoleCache(ctx context.Context, userID, orgID string)
- func (e *Engine) PrepareContext(ctx context.Context) (context.Context, error)
- func (e *Engine) Require(ctx context.Context, checks ...Check) error
- func (e *Engine) RequireAny(ctx context.Context, checks ...Check) error
- func (e *Engine) ShouldEnforce(ctx context.Context) (bool, error)
- type EngineOpts
- type Grant
- func GrantsFromContext(ctx context.Context) ([]Grant, bool)
- func GrantsFromOverrides(overrides []RoleGrant) []Grant
- func LoadGrants(ctx context.Context, db accessrepo.DBTX, organizationID string, ...) ([]Grant, error)
- func NewGrant(scope Scope, resourceID string) Grant
- func NewGrantWithSelector(scope Scope, selector Selector) Grant
- type InvalidCheckError
- type IsRBACEnabled
- type MCPToolCallDimensions
- type MembershipFetcher
- type RoleGrant
- type Scope
- type ScopedGrant
- type Selector
Constants ¶
const ( SystemRoleAdmin = "admin" SystemRoleMember = "member" )
const ( DispositionReadOnly = "read_only" DispositionDestructive = "destructive" DispositionIdempotent = "idempotent" DispositionOpenWorld = "open_world" )
Disposition values matching MCP tool annotation hint names (snake_case, no _hint suffix).
const WildcardResource = "*"
Variables ¶
var ErrDenied = errors.New("authz denied")
var ErrInvalidCheck = errors.New("invalid authz check")
var ErrMissingGrants = errors.New("authz grants missing from context")
var ErrNoChecks = errors.New("at least one authz check is required")
var SystemRoleGrants = map[string][]*RoleGrant{ SystemRoleAdmin: { {Scope: string(ScopeOrgAdmin)}, {Scope: string(ScopeOrgRead)}, {Scope: string(ScopeProjectRead)}, {Scope: string(ScopeProjectWrite)}, {Scope: string(ScopeMCPRead)}, {Scope: string(ScopeMCPWrite)}, {Scope: string(ScopeMCPConnect)}, {Scope: string(ScopeEnvironmentRead)}, {Scope: string(ScopeEnvironmentWrite)}, }, SystemRoleMember: { {Scope: string(ScopeOrgRead)}, {Scope: string(ScopeProjectRead)}, {Scope: string(ScopeMCPRead)}, {Scope: string(ScopeMCPConnect)}, {Scope: string(ScopeEnvironmentRead)}, }, }
SystemRoleGrants defines the canonical grant sets for the built-in system roles. These are seeded when RBAC is enabled and replace any existing grants for these roles (idempotent, won't clobber custom roles).
Functions ¶
func CalculateSubScopes ¶
func GrantsToContext ¶
GrantsToContext stores resolved grants on the request context.
func InvalidCheck ¶
func ResourceKindForScope ¶
ResourceKindForScope derives the resource kind from a scope's family prefix.
func SeedSystemRoleGrants ¶
func SeedSystemRoleGrants(ctx context.Context, logger *slog.Logger, db *pgxpool.Pool, organizationID string) error
SeedSystemRoleGrants upserts the fixed grant sets for all system roles.
func SyncGrants ¶
func ValidateSelector ¶
ValidateSelector checks that a selector is well-formed for the given scope. Rules:
- resource_kind and resource_id must both be present
- resource_kind must match the scope family (or be "*" for root)
- extra keys must be in the allowed set for the scope family
- unknown keys are rejected
Types ¶
type ChallengeLoggingEnabled ¶
ChallengeLoggingEnabled checks whether authz challenge logging to ClickHouse is enabled for a given organization. Same signature as IsRBACEnabled.
type Check ¶
type Check struct {
Scope Scope
ResourceKind string
ResourceID string
Dimensions map[string]string
}
Check describes a single authorization requirement. ResourceID identifies the resource. ResourceKind overrides the kind derived from the scope — leave empty to derive automatically. Dimensions carry optional narrowing attributes (tool, disposition, collection) for multi-dimensional checks.
func MCPCheck ¶
MCPCheck builds a Check for an MCP scope (read/write/connect) with project_id injected as a dimension so project-scoped grants can match.
func MCPToolCallCheck ¶
func MCPToolCallCheck(toolsetID string, dims MCPToolCallDimensions) Check
MCPToolCallCheck builds a Check for an MCP tool call with the given dimensions.
type DeniedError ¶
func (*DeniedError) Error ¶
func (e *DeniedError) Error() string
func (*DeniedError) Unwrap ¶
func (e *DeniedError) Unwrap() error
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
func NewEngine ¶
func NewEngine(logger *slog.Logger, db *pgxpool.Pool, chDB clickhouse.Conn, isEnabled IsRBACEnabled, challengeLogging ChallengeLoggingEnabled, membership MembershipFetcher, roleCache cache.Cache, opts ...EngineOpts) *Engine
func (*Engine) Filter ¶
Filter evaluates each check and returns the resource IDs of those the caller is authorized for. When RBAC is not enforced all resource IDs are returned.
func (*Engine) GetScopeOverrides ¶
GetScopeOverrides returns the parsed scope overrides from the request context if they are present AND the caller is authorised to use them. In local dev any authenticated user may use the override header; in production only superadmins can. Returns nil, false when overrides are absent or disallowed.
func (*Engine) InvalidateAllRoleCaches ¶
InvalidateAllRoleCaches removes all cached role slugs for an org. Call this after bulk role reassignments where individual user IDs aren't tracked.
func (*Engine) InvalidateRoleCache ¶
InvalidateRoleCache removes the cached role slug for a single user. Call this after updating a specific member's role via UpdateMemberRole.
func (*Engine) PrepareContext ¶
type EngineOpts ¶
type EngineOpts struct {
DevMode bool
}
type Grant ¶
func GrantsFromContext ¶
GrantsFromContext loads resolved grants from the request context.
func GrantsFromOverrides ¶
GrantsFromOverrides builds a Grants slice from parsed scope overrides. Scopes with no selectors get wildcard access; scopes with selectors get one grant per selector. For backward compatibility with the header format, bare resource IDs are converted to selectors via NewSelector.
func LoadGrants ¶
func LoadGrants(ctx context.Context, db accessrepo.DBTX, organizationID string, principals []urn.Principal) ([]Grant, error)
LoadGrants loads and normalizes grants for the given organization and principals.
func NewGrantWithSelector ¶
NewGrantWithSelector creates a Grant with an explicit selector.
type InvalidCheckError ¶
type InvalidCheckError struct {
Scope Scope
ResourceID string
// contains filtered or unexported fields
}
func (*InvalidCheckError) Error ¶
func (e *InvalidCheckError) Error() string
func (*InvalidCheckError) Unwrap ¶
func (e *InvalidCheckError) Unwrap() error
type IsRBACEnabled ¶
type MCPToolCallDimensions ¶
MCPToolCallDimensions carries the typed attributes of an MCP tool call. Zero-value fields are omitted from the check dimensions.
type MembershipFetcher ¶
type MembershipFetcher interface {
GetOrgMembership(ctx context.Context, workOSUserID, workOSOrgID string) (*workos.Member, error)
}
MembershipFetcher retrieves a WorkOS membership for a user+org pair.
type Scope ¶
type Scope string
Scope identifies an authorization capability granted on a resource.
const ( ScopeRoot Scope = "root" ScopeOrgRead Scope = "org:read" ScopeOrgAdmin Scope = "org:admin" ScopeProjectRead Scope = "project:read" ScopeProjectWrite Scope = "project:write" ScopeMCPRead Scope = "mcp:read" ScopeMCPWrite Scope = "mcp:write" ScopeMCPConnect Scope = "mcp:connect" ScopeEnvironmentRead Scope = "environment:read" ScopeEnvironmentWrite Scope = "environment:write" )
type ScopedGrant ¶
func GrantsForRole ¶
func GrantsToScopedGrants ¶
func GrantsToScopedGrants(rows []Grant) []*ScopedGrant
GrantsToScopedGrants groups raw grants by scope, collapsing wildcards.
type Selector ¶
Selector is a set of key-value constraints attached to a grant or check. Grants use explicit resource_kind and resource_id keys, e.g. {"resource_kind":"project","resource_id":"proj_123"}. Wildcard uses {"resource_kind":"*","resource_id":"*"}. For a grant selector to match a check selector, every key in the grant must either equal the corresponding check value or be the wildcard "*".
func NewSelector ¶
NewSelector creates a selector with resource_kind derived from scope.
func SelectorFromRow ¶
SelectorFromRow parses the selectors JSONB column into a Selector.
func (Selector) MarshalJSON ¶
MarshalJSON implements json.Marshaler. A nil selector marshals as the explicit wildcard {"resource_kind":"*","resource_id":"*"}.
func (Selector) Matches ¶
Matches reports whether this (grant) selector satisfies the given check selector. A nil/empty grant selector matches any check (defensive fallback). For each key present in BOTH the grant and check selectors, the values must be equal or the grant value must be "*". Keys present in the grant but absent from the check are skipped — the check is not constraining that dimension. This allows disposition-scoped grants (e.g. {"disposition":"read_only"}) to match connection-level checks that don't yet specify a disposition.
func (Selector) ResourceID ¶
ResourceID extracts the resource_id value from the selector. Returns "*" if no resource_id key is present.