engine

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2026 License: MIT Imports: 39 Imported by: 0

Documentation

Overview

Package engine provides the layered safety execution engine.

The engine runs content through six layers modeled on human safety cognition, in this order, and then the tenant's policies:

Layer 1: INSTINCTS    injection, jailbreak, exfiltration and manipulation patterns
Layer 2: AWARENESS    PII, secret, topic and custom pattern detectors
Layer 3: BOUNDARIES   topic, data, output and tool-call (action) limits
Layer 4: VALUES       safety and toxicity lexicons, custom terms and patterns
Layer 5: JUDGMENT     risk over the findings so far, plus the optional model judge
Layer 6: REFLEXES     trigger and action rules
then:    POLICIES     the tenant's org-level and assigned app-level rules

Every scan runs inside a tenant and evaluates one safety profile of that tenant, compiled from the store and cached (see Config.ProfileCacheTTL), then the tenant's policies. With Config.EnableShortCircuit a block ends the scan after the layer that found it.

Index

Constants

View Source
const (
	ScansCompletedMetric = "shield_scans_completed_total"
	ScanDurationMetric   = "shield_scan_duration_seconds"
)

The metrics the engine records when WithMetrics is set. A Forge app scrapes them with a forge_ prefix: forge_shield_scans_completed_total and forge_shield_scan_duration_seconds. Both carry direction (input, output, tool_call) and decision (allow, block, flag, redact, require_approval).

View Source
const MaxArgumentDepth = 32

MaxArgumentDepth bounds how deeply the JSON arguments of a tool call may nest objects and arrays. Deeper arguments are shield.ErrInvalidInput. Tool arguments are flat in practice; the bound keeps a hostile body from costing a deep walk.

View Source
const MaxProfilePatterns = 256

MaxProfilePatterns bounds the regexes and globs operators write into one compiled profile: instinct, awareness and values patterns, reflex patterns, targets and globs. Each regex without a literal prefix costs a pass over the text, so the bound keeps one tenant's scans from costing seconds.

View Source
const MaxRateThreshold = 100000

MaxRateThreshold is the largest on_rate threshold: more scans than this within a window are never counted. Thresholds are whole numbers.

Variables

View Source
var ScanDurationBuckets = []float64{0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5}

ScanDurationBuckets are the histogram bounds for ScanDurationMetric, in seconds. They span the layer budgets, from a 5ms boundary check to a 500ms judgment, with headroom for storing the result.

Functions

func ActionGlob

func ActionGlob(entry string) (glob string, risk bool)

ActionGlob splits an action-scope boundary entry into its path.Match glob and what it matches: the risk class for an entry with a risk: prefix (in any case), the tool name otherwise. The entry and the glob after the prefix are trimmed.

Types

type Capabilities

type Capabilities struct {
	Persistence      bool `json:"persistence"`
	Evaluation       bool `json:"evaluation"`
	ToolCalls        bool `json:"tool_calls"`
	ModelJudge       bool `json:"model_judge"`
	ReportGeneration bool `json:"report_generation"`
	ConfigWrite      bool `json:"config_write"`
	// Layers lists the layers that cannot run. It is empty, never nil.
	Layers []string `json:"unavailable_layers"`
	// Supported names what the engine runs, sorted, under the keys
	// instinct_strategies, awareness_detectors, judgment_assessors,
	// reflex_triggers and values_lexicons (the principles with a built-in
	// detector). unavailable_judgment_assessors names the assessors a
	// judgment may list that the engine skips: model, unless
	// Config.ModelJudge is on and a judge is registered.
	Supported map[string][]string `json:"supported"`
}

Capabilities describes implemented services, independently of configured rows.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the core safety execution engine.

func New

func New(opts ...Option) (*Engine, error)

New creates a new safety engine with the given options.

func (*Engine) Capabilities

func (e *Engine) Capabilities() Capabilities

Capabilities reports what this engine can do.

func (*Engine) Config

func (e *Engine) Config() shield.Config

Config returns a copy of the effective engine configuration.

func (*Engine) Health

func (e *Engine) Health(ctx context.Context) error

Health checks the health of the engine by pinging its store.

func (*Engine) InvalidateAllProfiles

func (e *Engine) InvalidateAllProfiles()

InvalidateAllProfiles drops every tenant's cached profiles, so each tenant's next scan loads its profile and policies again. Call it after changing an app-level policy outside the admin service, which calls it for you: every tenant the policy is assigned to compiles it in.

func (*Engine) InvalidateProfiles

func (e *Engine) InvalidateProfiles(tenantID string)

InvalidateProfiles drops every cached profile of tenantID, so the next scan for that tenant loads its profile and primitives again. Call it after changing a tenant's safety rows outside the admin service, which calls it for you.

func (*Engine) ProfileGeneration

func (e *Engine) ProfileGeneration(tenantID string) uint64

ProfileGeneration returns a number that changes whenever InvalidateProfiles(tenantID) or InvalidateAllProfiles runs. A host that caches scan verdicts keys them on it, so a profile change made through the admin service (or followed by an invalidation) is never answered from a stale verdict.

func (*Engine) ScanInput

func (e *Engine) ScanInput(ctx context.Context, input *scan.Input) (*scan.Result, error)

ScanInput runs a safety scan on input content (user→agent).

func (*Engine) ScanOutput

func (e *Engine) ScanOutput(ctx context.Context, input *scan.Input) (*scan.Result, error)

ScanOutput runs a safety scan on output content (agent→user).

func (*Engine) ScanToolCall

func (e *Engine) ScanToolCall(ctx context.Context, in *scan.ToolCallInput) (*scan.Result, error)

ScanToolCall evaluates a proposed tool call. The decision is allow, block or require_approval. It is advisory and can only restrict: the host enforces its own risk table first and combines with scan.Stricter, so nothing here can turn a host refusal into an allow.

Every object key, whatever its value, and every string and number value of the arguments is a unit, scanned on its own and unchanged, the way ScanInput would see that text, with Direction tool_call. Keys come sorted, each before what it holds. A finding from a unit lists the JSON path of each unit in its paths details (a.b.0, key:a.b for a key, $ for a top-level value); a key that is not a short identifier, that a layer found something in, or that a built-in secret or personal data detector matches whatever the profile runs, shows as #N, its place among its sorted siblings. The judge's lines name units the same way. Topic and data boundaries match the units joined by newlines. Action boundaries match the tool name, or with a risk: prefix the risk class. on_context reflexes see tool, risk_class (unknown when empty) and every Metadata key. The result never carries text, and the stored scan keeps the tool, the risk class and the metadata but no argument.

Besides the errors of ScanInput, a nil input, a blank Tool or one holding a control or invisible rune, and arguments that are not one JSON value or nest deeper than MaxArgumentDepth are shield.ErrInvalidInput. Arguments, tool, risk class and metadata over Config.MaxScanBytes are shield.ErrInputTooLarge.

func (*Engine) Stop

func (e *Engine) Stop(ctx context.Context) error

Stop gracefully shuts down the engine.

func (*Engine) Store

func (e *Engine) Store() store.Store

Store returns the composite store (may be nil if not configured).

type Option

type Option func(*Engine)

Option configures the Engine.

func WithConfig

func WithConfig(cfg shield.Config) Option

WithConfig sets the engine configuration.

func WithJudge

func WithJudge(j judgment.Judge) Option

WithJudge registers the model judge. It is called only when Config.ModelJudge is true, and it can only raise a judgment's risk.

func WithLogger

func WithLogger(l log.Logger) Option

WithLogger sets a custom logger. The plugin registry reports hook errors on it too.

func WithMetrics

func WithMetrics(m gometrics.Metrics) Option

WithMetrics records scan and plugin metrics on m: ScansCompletedMetric, ScanDurationMetric and plugin.HooksFailedMetric. In a Forge app pass app.Metrics(); the Shield Forge extension does this for you. A nil m, the default, records nothing.

func WithPlugin

func WithPlugin(p plugin.Plugin) Option

WithPlugin registers a lifecycle plugin.

func WithStore

func WithStore(s store.Store) Option

WithStore sets the composite store.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL