snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
141
internal/check/definitions.go
Normal file
141
internal/check/definitions.go
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright © 2026 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package check
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ory/keto/internal/relationtuple"
|
||||
)
|
||||
|
||||
type (
|
||||
// Result holds the outcome of a single permission check.
|
||||
// Limitation is non-empty only when Membership is MembershipUnknown.
|
||||
Result struct {
|
||||
Membership Membership
|
||||
Err error
|
||||
Limitation LimitationKind
|
||||
}
|
||||
|
||||
Membership int
|
||||
|
||||
// LimitationKind identifies which traversal constraint was hit. A non-empty
|
||||
// value on a Result means the membership answer is indeterminate.
|
||||
LimitationKind string
|
||||
)
|
||||
|
||||
//go:generate stringer -type Membership
|
||||
const (
|
||||
MembershipUnknown Membership = iota
|
||||
IsMember
|
||||
NotMember
|
||||
)
|
||||
|
||||
const (
|
||||
LimitationMaxDepthExceeded LimitationKind = "max_depth_exceeded"
|
||||
LimitationMaxWidthExceeded LimitationKind = "max_width_exceeded"
|
||||
)
|
||||
|
||||
var (
|
||||
ResultUnknown = Result{Membership: MembershipUnknown}
|
||||
ResultIsMember = Result{Membership: IsMember}
|
||||
ResultNotMember = Result{Membership: NotMember}
|
||||
)
|
||||
|
||||
// CheckRequest carries all inputs for a single check evaluation step.
|
||||
type CheckRequest struct {
|
||||
Tuple *relationtuple.RelationTuple
|
||||
RestDepth int
|
||||
}
|
||||
|
||||
func (r CheckRequest) WithDepth(d int) CheckRequest {
|
||||
r.RestDepth = d
|
||||
return r
|
||||
}
|
||||
|
||||
// PlannedStep pairs a Step with the CheckRequest it should run against.
|
||||
type PlannedStep struct {
|
||||
Step Step
|
||||
Req CheckRequest
|
||||
}
|
||||
|
||||
// StepRunner orchestrates execution of multiple steps with short-circuit semantics.
|
||||
// Typical usage:
|
||||
//
|
||||
// runner := ex.NewUnionRunner(ctx)
|
||||
// for _, ps := range steps {
|
||||
// if runner.Done() { break }
|
||||
// runner.Add(ps)
|
||||
// }
|
||||
// return runner.Result()
|
||||
type StepRunner interface {
|
||||
// Add enqueues a step for execution. Returns early if Done() is true.
|
||||
// No-op if the runner has already reached a decisive result or been cancelled.
|
||||
Add(PlannedStep)
|
||||
|
||||
// Done reports whether a decisive result was reached or context cancelled.
|
||||
// Use to short-circuit the enqueue loop.
|
||||
Done() bool
|
||||
|
||||
// Ctx returns the runner's context, usable for shared state like visited tracking.
|
||||
// The context is cancelled when a decisive result is reached (to signal siblings).
|
||||
Ctx() context.Context
|
||||
|
||||
// AddLimitation records that some branches were skipped due to given [LimitationKind] constraint.
|
||||
AddLimitation(LimitationKind)
|
||||
|
||||
// Result waits for all in-flight steps to complete and returns the aggregated result.
|
||||
// Call it after the Add loop finishes (or breaks early on Done()).
|
||||
Result() Result
|
||||
}
|
||||
|
||||
// Executor coordinates permission check execution with middleware support.
|
||||
// It runs individual steps (Run), sequences steps with union/intersection logic
|
||||
// (RunUnion, RunIntersection), and supports custom execution strategies via
|
||||
// middleware. All Executor implementations are stateless; dependencies come
|
||||
// from EngineDependencies.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
// result := executor.Run(ctx, DirectStep{}, req)
|
||||
// unionResult := executor.RunUnion(ctx, step1, step2)
|
||||
// intersectionResult := executor.RunIntersection(ctx, step1, step2)
|
||||
type Executor interface {
|
||||
// Run executes a single step through the middleware chain.
|
||||
Run(ctx context.Context, step Step, req CheckRequest) Result
|
||||
|
||||
// RunUnion runs steps with OR semantics: returns IsMember on first match,
|
||||
// short-circuits siblings, falls through to NotMember if none match.
|
||||
RunUnion(ctx context.Context, steps ...PlannedStep) Result
|
||||
|
||||
// RunIntersection runs steps with AND semantics: returns NotMember or Error
|
||||
// on first failure, short-circuits siblings.
|
||||
RunIntersection(ctx context.Context, steps ...PlannedStep) Result
|
||||
|
||||
// NewUnionRunner creates a StepRunner for streaming union execution.
|
||||
// It is useful when Steps are created dynamically and the full list is not known upfront.
|
||||
NewUnionRunner(ctx context.Context) StepRunner
|
||||
|
||||
Deps() EngineDependencies
|
||||
}
|
||||
|
||||
// Middleware intercepts a step execution within the pipeline. next continues
|
||||
// down the remaining middlewares and ultimately calls step.Execute.
|
||||
type Middleware func(
|
||||
ctx context.Context,
|
||||
step Step,
|
||||
req CheckRequest,
|
||||
next func(context.Context, Step, CheckRequest) Result,
|
||||
) Result
|
||||
|
||||
// Checker performs a full permission check for a single relation tuple.
|
||||
// Implemented by Executor in the step package.
|
||||
type (
|
||||
CheckerProvider interface {
|
||||
Checker() Checker
|
||||
}
|
||||
Checker interface {
|
||||
CheckRelationTuple(ctx context.Context, r *relationtuple.RelationTuple, restDepth int) Result
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user