Documentation
¶
Overview ¶
Package dsl parses, compiles, serializes, and evaluates Conductera authorization schemas.
The package is deterministic and storage-agnostic. Callers provide relationship data at check time through the TupleReader interface.
CompileArtifact produces a canonical, immutable v1 artifact for durable or remote transport and guarantees that successful output decodes under default artifact limits. CompileArtifactWithLimits provides the same guarantee when decoded with the matching program limits and DefaultArtifactMaxBytes. V1 canonical IR has a stable structural nesting cap of ArtifactFormatV1MaxNestingDepth, enforced by producers and by readers before typed IR decoding. DecodeArtifact strictly validates compatibility, canonical JSON and IR, the domain-separated digest, and caller-provided work limits before returning its executable Program. Artifact failures expose stable public error-code constants and defensively copied, source-located, message-redacted diagnostics. V1 golden bytes live under conformance/artifacts/v1 as an append-only compatibility history.
Example ¶
package main
import (
"context"
"fmt"
"github.com/cadrena/dsl"
)
func main() {
program, err := dsl.Compile("example.cdr", []byte(`
entity user {}
entity document {
relation viewer @user
action view = viewer
}
`))
if err != nil {
panic(err)
}
tuples, err := dsl.NewTupleSet([]dsl.Tuple{{
Resource: dsl.EntityRef{Type: "document", ID: "roadmap"},
Relation: "viewer",
Subject: dsl.SubjectRef{Type: "user", ID: "alice"},
}})
if err != nil {
panic(err)
}
result, err := program.Check(context.Background(), dsl.Request{
Subject: dsl.EntityRef{Type: "user", ID: "alice"},
Resource: dsl.EntityRef{Type: "document", ID: "roadmap"},
Action: "view",
}, tuples)
if err != nil {
panic(err)
}
fmt.Println(result.Decision)
fmt.Println(result.Reason)
}
Output: allow GRAPH_ALLOWED
Index ¶
- Constants
- type Action
- type ActionDescriptor
- type ActionRef
- type Artifact
- func CompileArtifact(sourceName string, source []byte) (*Artifact, error)
- func CompileArtifactWithLimits(sourceName string, source []byte, limits Limits) (*Artifact, error)
- func DecodeArtifact(data []byte) (*Artifact, error)
- func DecodeArtifactWithLimits(data []byte, limits ArtifactDecodeLimits) (*Artifact, error)
- type ArtifactCapability
- type ArtifactDecodeLimits
- type ArtifactDiagnostic
- type ArtifactDiagnostics
- type ArtifactError
- type ArtifactManifest
- type BinaryExpression
- type BinaryOperator
- type CheckError
- type ComparisonExpression
- type ComparisonOperator
- type ConditionExpression
- type Decision
- type Diagnostic
- type Diagnostics
- type Entity
- type EntityRef
- type GraphExpression
- type Guard
- type GuardEffect
- type GuardMatch
- type GuardRule
- type Limits
- type Literal
- type LiteralKind
- type LogicalCondition
- type Permission
- type Position
- type Program
- type ReferenceExpression
- type Relation
- type RelationTarget
- type Request
- type Result
- type Schema
- type SubjectRef
- type TraceStep
- type Tuple
- type TupleReader
- type TupleSet
Examples ¶
Constants ¶
const ( // ArtifactFormatV1 is the first stable artifact envelope and canonical IR format. ArtifactFormatV1 uint32 = 1 // ArtifactFormatV1MaxNestingDepth is the maximum canonical IR structural // container depth accepted or emitted by the stable v1 format. The bound // leaves headroom below encoding/json's envelope nesting ceiling even when // callers raise the program expression-node limits. ArtifactFormatV1MaxNestingDepth = 4096 // DefaultArtifactMaxBytes is the maximum artifact envelope size emitted by // compilation and accepted by DecodeArtifact. DefaultArtifactMaxBytes = 8 << 20 // LanguageVersionV1 identifies the Cadrena DSL language accepted by v1 artifacts. LanguageVersionV1 = "conductera/v1" // EvaluatorABIV1 identifies the evaluator semantics required by v1 artifacts. EvaluatorABIV1 = "conductera-evaluator/v1" )
const ( ArtifactErrorCodeLimitInvalid = "E_ARTIFACT_LIMIT_INVALID" ArtifactErrorCodeSourceInvalid = "E_ARTIFACT_SOURCE_INVALID" ArtifactErrorCodeInvalidIR = "E_ARTIFACT_INVALID_IR" ArtifactErrorCodeMalformed = "E_ARTIFACT_MALFORMED" ArtifactErrorCodeTooLarge = "E_ARTIFACT_TOO_LARGE" ArtifactErrorCodeDigestMismatch = "E_ARTIFACT_DIGEST_MISMATCH" ArtifactErrorCodeNonCanonical = "E_ARTIFACT_NON_CANONICAL" ArtifactErrorCodeVersionUnsupported = "E_ARTIFACT_VERSION_UNSUPPORTED" ArtifactErrorCodeLanguageUnsupported = "E_ARTIFACT_LANGUAGE_UNSUPPORTED" ArtifactErrorCodeABIUnsupported = "E_ARTIFACT_ABI_UNSUPPORTED" ArtifactErrorCodeCapabilityUnsupported = "E_ARTIFACT_CAPABILITY_UNSUPPORTED" ArtifactErrorCodeCapabilityMismatch = "E_ARTIFACT_CAPABILITY_MISMATCH" ArtifactErrorCodeLimitExceeded = "E_ARTIFACT_LIMIT_EXCEEDED" ArtifactErrorCodeNil = "E_ARTIFACT_NIL" ArtifactErrorCodeInvalid = "E_ARTIFACT_INVALID" )
Stable ArtifactError.Code values.
const ( // ReasonGraphAllowed means the graph action matched and no guard denied it. ReasonGraphAllowed = "GRAPH_ALLOWED" // ReasonGraphDenied means the graph action did not match. ReasonGraphDenied = "GRAPH_DENIED" // ReasonGuardAllowed means a guard allow rule won. ReasonGuardAllowed = "GUARD_ALLOWED" // ReasonGuardDenied means a guard deny rule won or no guard allow matched. ReasonGuardDenied = "GUARD_DENIED" // ReasonApprovalRequired means a guard requires external approval. ReasonApprovalRequired = "APPROVAL_REQUIRED" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Action ¶
type Action struct {
Name string
Expression GraphExpression
Position Position
}
Action declares an externally checkable graph expression.
type ActionDescriptor ¶
ActionDescriptor identifies an externally checkable action.
type Artifact ¶
type Artifact struct {
// contains filtered or unexported fields
}
Artifact is an opaque, immutable, deterministic compiled DSL artifact. Its exported accessors return defensive copies of mutable data. Only CompileArtifact and DecodeArtifact produce valid values; the zero value is invalid. Accessors are safe on a nil receiver and return their documented empty values, except MarshalBinary, which returns a typed error.
func CompileArtifact ¶
CompileArtifact compiles source into a deterministic v1 artifact using the default DSL safety limits. Failures are returned as *ArtifactError values whose display text and causes do not contain source contents.
func CompileArtifactWithLimits ¶
CompileArtifactWithLimits compiles source into a deterministic v1 artifact using caller-provided DSL safety limits and DefaultArtifactMaxBytes as the final wire-size budget. Every successful result can be decoded with ArtifactDecodeLimits{MaxBytes: DefaultArtifactMaxBytes, Program: limits}. Failures are returned as *ArtifactError values whose display text and causes do not contain source contents.
func DecodeArtifact ¶
DecodeArtifact validates and loads a canonical v1 artifact using default artifact and program safety limits. Failures are returned as *ArtifactError values whose display text and causes do not contain artifact contents.
func DecodeArtifactWithLimits ¶
func DecodeArtifactWithLimits(data []byte, limits ArtifactDecodeLimits) (*Artifact, error)
DecodeArtifactWithLimits validates and loads a canonical v1 artifact using caller-provided byte and hydrated program safety limits. Compatibility and capability checks occur before Program hydration. Failures are returned as *ArtifactError values without artifact contents in diagnostics.
func (*Artifact) CanonicalIR ¶
CanonicalIR returns the deterministic versioned IR bytes. The returned bytes do not alias artifact state. A nil receiver returns a non-nil empty slice.
func (*Artifact) CanonicalSource ¶
CanonicalSource returns deterministic DSL source reconstructed from the canonical IR. The returned bytes do not alias artifact state. A nil receiver returns a non-nil empty slice.
func (*Artifact) Digest ¶
Digest returns the domain-separated SHA-256 digest binding the manifest and canonical IR. A nil receiver returns the zero digest.
func (*Artifact) Manifest ¶
func (a *Artifact) Manifest() ArtifactManifest
Manifest returns the artifact compatibility manifest with a defensive copy of its capability list. A nil receiver returns an empty manifest with a non-nil empty capability list.
func (*Artifact) MarshalBinary ¶
MarshalBinary returns a defensive copy of the canonical v1 artifact envelope bytes. It returns E_ARTIFACT_NIL for a nil receiver and E_ARTIFACT_INVALID for an uninitialized zero value.
type ArtifactCapability ¶
type ArtifactCapability string
ArtifactCapability identifies a required artifact evaluator capability.
const ( // CapabilityGraphV1 identifies v1 relationship graph evaluation. CapabilityGraphV1 ArtifactCapability = "graph/v1" // CapabilityGuardsV1 identifies v1 parameter guard evaluation. CapabilityGuardsV1 ArtifactCapability = "guards/v1" )
type ArtifactDecodeLimits ¶
type ArtifactDecodeLimits struct {
// MaxBytes is the maximum accepted artifact envelope size.
MaxBytes int
// Program bounds canonical source, IR work, and the hydrated Program.
Program Limits
}
ArtifactDecodeLimits bounds artifact decoding and hydrated program work. MaxBytes and every field in Program must be greater than zero.
func DefaultArtifactDecodeLimits ¶
func DefaultArtifactDecodeLimits() ArtifactDecodeLimits
DefaultArtifactDecodeLimits returns the v1 artifact and program safety limits.
type ArtifactDiagnostic ¶
ArtifactDiagnostic is a redacted, source-located diagnostic exposed by the Artifact API. It intentionally omits the original diagnostic message and any source token text.
type ArtifactDiagnostics ¶
type ArtifactDiagnostics struct {
// contains filtered or unexported fields
}
ArtifactDiagnostics is an errors.As-compatible redacted diagnostic cause. Use All to inspect its diagnostics.
func (*ArtifactDiagnostics) All ¶
func (d *ArtifactDiagnostics) All() []ArtifactDiagnostic
All returns a defensive copy of the redacted source-located diagnostics.
func (*ArtifactDiagnostics) Error ¶
func (d *ArtifactDiagnostics) Error() string
Error returns only the diagnostic category and stable codes. Source names, locations, messages, source text, and artifact bytes are omitted.
type ArtifactError ¶
type ArtifactError struct {
// Code is the stable machine-readable error code.
Code string
// Message is a safe human-readable summary without input contents.
Message string
// Cause is an optional sanitized diagnostic category. Errors produced by
// this package never place source or artifact contents in Cause.
Cause error
}
ArtifactError is a stable artifact compilation or decoding error. Code is suitable for programmatic handling; Message is safe for display.
func (*ArtifactError) Diagnostics ¶
func (e *ArtifactError) Diagnostics() []ArtifactDiagnostic
Diagnostics returns the redacted source-located diagnostics carried by this error. It returns a non-nil empty slice when no diagnostics are available.
func (*ArtifactError) Error ¶
func (e *ArtifactError) Error() string
Error returns the stable artifact error code and safe display message. Cause details are intentionally omitted; callers may inspect the sanitized cause with errors.Unwrap.
func (*ArtifactError) Unwrap ¶
func (e *ArtifactError) Unwrap() error
Unwrap returns the sanitized diagnostic cause, if any.
type ArtifactManifest ¶
type ArtifactManifest struct {
// FormatVersion identifies the artifact envelope and canonical IR format.
FormatVersion uint32
// LanguageVersion identifies the DSL source semantics.
LanguageVersion string
// EvaluatorABI identifies the required evaluation semantics.
EvaluatorABI string
// Capabilities lists required evaluator features in canonical order.
Capabilities []ArtifactCapability
// MaxGraphDepth is the graph depth embedded into the compiled Program.
MaxGraphDepth int
}
ArtifactManifest binds an artifact to its wire format, language, evaluator semantics, required capabilities, and graph evaluation depth.
type BinaryExpression ¶
type BinaryExpression struct {
Operator BinaryOperator
Left GraphExpression
Right GraphExpression
At Position
}
BinaryExpression combines two graph expressions with and/or.
func (BinaryExpression) Position ¶
func (e BinaryExpression) Position() Position
Position returns the expression's source location.
func (BinaryExpression) String ¶
func (e BinaryExpression) String() string
String returns a canonical expression that preserves precedence.
type BinaryOperator ¶
type BinaryOperator uint8
BinaryOperator combines two graph expressions.
const ( // OperatorAnd requires both operands to match. OperatorAnd BinaryOperator = iota + 1 // OperatorOr requires at least one operand to match. OperatorOr )
func (BinaryOperator) String ¶
func (o BinaryOperator) String() string
String returns the DSL spelling of the operator.
type CheckError ¶
CheckError is a stable runtime validation or evaluation error.
func (*CheckError) Error ¶
func (e *CheckError) Error() string
Error returns the runtime error message.
func (*CheckError) Unwrap ¶
func (e *CheckError) Unwrap() error
Unwrap returns the underlying reader or context error.
type ComparisonExpression ¶
type ComparisonExpression struct {
Field []string
Operator ComparisonOperator
Values []Literal
At Position
}
ComparisonExpression compares one runtime field with one or more literals.
func (ComparisonExpression) Position ¶
func (e ComparisonExpression) Position() Position
Position returns the expression's source location.
func (ComparisonExpression) String ¶
func (e ComparisonExpression) String() string
String returns the canonical source form of the comparison.
type ComparisonOperator ¶
type ComparisonOperator uint8
ComparisonOperator compares a runtime field with a literal.
const ( // ComparisonEqual performs typed equality. ComparisonEqual ComparisonOperator = iota + 1 // ComparisonNotEqual performs typed inequality. ComparisonNotEqual // ComparisonLess performs integer less-than comparison. ComparisonLess // ComparisonLessOrEqual performs integer less-than-or-equal comparison. ComparisonLessOrEqual // ComparisonGreater performs integer greater-than comparison. ComparisonGreater // ComparisonGreaterOrEqual performs integer greater-than-or-equal comparison. ComparisonGreaterOrEqual // ComparisonIn performs typed set membership. ComparisonIn )
func (ComparisonOperator) String ¶
func (o ComparisonOperator) String() string
String returns the DSL spelling of the comparison operator.
type ConditionExpression ¶
type ConditionExpression interface {
fmt.Stringer
Position() Position
// contains filtered or unexported methods
}
ConditionExpression is a typed parameter condition.
type Diagnostic ¶
Diagnostic is a stable, source-located lexical, parse, or semantic error.
func (Diagnostic) Error ¶
func (d Diagnostic) Error() string
Error returns a human-readable source diagnostic.
type Diagnostics ¶
type Diagnostics []Diagnostic
Diagnostics is a deterministic collection of source diagnostics.
func (Diagnostics) Error ¶
func (d Diagnostics) Error() string
Error returns all diagnostics separated by newlines.
type Entity ¶
type Entity struct {
Name string
Relations []Relation
Permissions []Permission
Actions []Action
Position Position
}
Entity declares one relationship-graph entity type.
type GraphExpression ¶
type GraphExpression interface {
fmt.Stringer
Position() Position
// contains filtered or unexported methods
}
GraphExpression is a relationship expression used by permissions and actions.
type GuardEffect ¶
type GuardEffect uint8
GuardEffect is the decision produced by a matching guard rule.
const ( // EffectAllow permits the action after graph authorization succeeds. EffectAllow GuardEffect = iota + 1 // EffectRequireApproval requires an external approval before execution. EffectRequireApproval // EffectDeny rejects the action. EffectDeny )
func (GuardEffect) String ¶
func (e GuardEffect) String() string
String returns the DSL spelling of the effect.
type GuardMatch ¶
type GuardMatch struct {
Effect GuardEffect
Approval string
}
GuardMatch records one matching guard effect without copying argument values.
type GuardRule ¶
type GuardRule struct {
Effect GuardEffect
Approval string
Condition ConditionExpression
Otherwise bool
Position Position
}
GuardRule declares one conditional guard effect.
type Limits ¶
type Limits struct {
MaxSourceBytes int
MaxEntities int
MaxDeclarationsPerEntity int
MaxRelationTargets int
MaxExpressionNodes int
MaxGuards int
MaxGuardRules int
MaxConditionNodes int
MaxGraphDepth int
}
Limits bounds parser, compiler, and evaluator work for untrusted policy input. Every field must be greater than zero.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns the v1 safety limits specified in SPEC.md.
type Literal ¶
type Literal struct {
Kind LiteralKind
String string
Integer int64
Boolean bool
}
Literal is a typed guard value. Only the field selected by Kind is meaningful.
type LiteralKind ¶
type LiteralKind uint8
LiteralKind identifies the type of a guard literal.
const ( // LiteralNull is the null literal. LiteralNull LiteralKind = iota + 1 // LiteralString is a UTF-8 string literal. LiteralString // LiteralInteger is a signed 64-bit integer literal. LiteralInteger // LiteralBoolean is a boolean literal. LiteralBoolean )
type LogicalCondition ¶
type LogicalCondition struct {
Operator BinaryOperator
Left ConditionExpression
Right ConditionExpression
At Position
}
LogicalCondition combines two parameter conditions with and/or.
func (LogicalCondition) Position ¶
func (e LogicalCondition) Position() Position
Position returns the expression's source location.
func (LogicalCondition) String ¶
func (e LogicalCondition) String() string
String returns the canonical source form of the condition.
type Permission ¶
type Permission struct {
Name string
Expression GraphExpression
Position Position
}
Permission declares a reusable graph expression.
type Program ¶
type Program struct {
// contains filtered or unexported fields
}
Program is an immutable, semantically validated authorization program. A Program is safe for concurrent checks when its TupleReader is safe for concurrent use.
func Compile ¶
Compile parses and semantically validates one DSL source file using the v1 default safety limits.
func CompileSchema ¶
CompileSchema semantically validates a parsed schema with default limits and returns an immutable program.
func CompileSchemaWithLimits ¶
CompileSchemaWithLimits semantically validates a parsed schema with explicit safety limits. The compiler does not retain or mutate caller-owned slices or maps.
func CompileWithLimits ¶
CompileWithLimits parses and semantically validates one DSL source file using caller-provided safety limits.
func (*Program) Actions ¶
func (p *Program) Actions() []ActionDescriptor
Actions returns every compiled action in deterministic entity/action order.
type ReferenceExpression ¶
ReferenceExpression refers to a local declaration or traverses a relation.
func (ReferenceExpression) Position ¶
func (e ReferenceExpression) Position() Position
Position returns the expression's source location.
func (ReferenceExpression) String ¶
func (e ReferenceExpression) String() string
String returns the canonical source form of the reference.
type Relation ¶
type Relation struct {
Name string
Targets []RelationTarget
Position Position
}
Relation declares the subject forms accepted by a named relation.
type RelationTarget ¶
RelationTarget identifies a direct entity or an entity userset.
type Request ¶
type Request struct {
Subject EntityRef
Resource EntityRef
Action string
Arguments map[string]any
ResourceAttributes map[string]any
MaxDepth int
}
Request contains inputs for one authorization check. MaxDepth zero uses the compiled program limit; a positive value may lower, but cannot raise, it. Callers must not mutate Arguments or ResourceAttributes during Check.
type Result ¶
type Result struct {
Decision Decision
Reason string
MatchedAction ActionRef
RequiredApprovals []string
MatchedGuards []GuardMatch
Trace []TraceStep
}
Result is the final decision and its deterministic explanation metadata.
type SubjectRef ¶
SubjectRef identifies a direct entity or an entity userset.
type Tuple ¶
type Tuple struct {
Resource EntityRef
Relation string
Subject SubjectRef
}
Tuple grants a relation on Resource to Subject.
type TupleReader ¶
type TupleReader interface {
ReadTuples(ctx context.Context, resource EntityRef, relation string) ([]SubjectRef, error)
}
TupleReader supplies relationship tuples to Program.Check. Implementations must return every tuple for the exact resource and relation. Returned order does not affect evaluation.
type TupleSet ¶
type TupleSet struct {
// contains filtered or unexported fields
}
TupleSet is an immutable in-memory TupleReader suitable for tests, examples, embedded policies, and small static datasets.
func NewTupleSet ¶
NewTupleSet validates and indexes tuples into an immutable reader.
func (*TupleSet) ReadTuples ¶
func (s *TupleSet) ReadTuples(ctx context.Context, resource EntityRef, relation string) ([]SubjectRef, error)
ReadTuples returns a defensive copy of subjects for resource and relation.