58 lines
1.9 KiB
Go
58 lines
1.9 KiB
Go
package policy
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
// ErrPolicyEvalFailed marks failures that must be treated as fail-closed
|
||
|
|
// policy evaluation outcomes.
|
||
|
|
ErrPolicyEvalFailed = errors.New("policy eval failed")
|
||
|
|
// ErrPolicyEvalTimeout marks evaluations that exceeded the eval budget. It
|
||
|
|
// always accompanies ErrPolicyEvalFailed (fail-closed consumers keep
|
||
|
|
// working unchanged) but lets operators and the activation guard tell a
|
||
|
|
// slow policy apart from a broken one.
|
||
|
|
ErrPolicyEvalTimeout = errors.New("policy eval timed out")
|
||
|
|
// ErrPolicySlowEval marks a policy source rejected by the activation-time
|
||
|
|
// cost guard: evaluating it exceeded the configured eval budget, so
|
||
|
|
// activating it would convert to request-path failures for every viewer.
|
||
|
|
ErrPolicySlowEval = errors.New("policy evaluation exceeds the eval budget")
|
||
|
|
// ErrUnknownDecision marks requests for a decision that is not loaded.
|
||
|
|
ErrUnknownDecision = errors.New("unknown policy decision")
|
||
|
|
// ErrCompileFailed marks policy compilation failures with structured issues.
|
||
|
|
ErrCompileFailed = errors.New("policy compile failed")
|
||
|
|
)
|
||
|
|
|
||
|
|
// CompileIssue identifies one policy compiler diagnostic.
|
||
|
|
type CompileIssue struct {
|
||
|
|
Row int `json:"row"`
|
||
|
|
Col int `json:"col"`
|
||
|
|
Message string `json:"message"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// CompileError carries structured policy compiler diagnostics.
|
||
|
|
type CompileError struct {
|
||
|
|
Issues []CompileIssue `json:"errors"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (e *CompileError) Error() string {
|
||
|
|
if e == nil || len(e.Issues) == 0 {
|
||
|
|
return ErrCompileFailed.Error()
|
||
|
|
}
|
||
|
|
messages := make([]string, 0, len(e.Issues))
|
||
|
|
for _, issue := range e.Issues {
|
||
|
|
if issue.Row > 0 || issue.Col > 0 {
|
||
|
|
messages = append(messages, fmt.Sprintf("%d:%d: %s", issue.Row, issue.Col, issue.Message))
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
messages = append(messages, issue.Message)
|
||
|
|
}
|
||
|
|
return fmt.Sprintf("%s: %s", ErrCompileFailed, strings.Join(messages, "; "))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (e *CompileError) Is(target error) bool {
|
||
|
|
return target == ErrCompileFailed
|
||
|
|
}
|