engine

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrSolutionFound = errors.New("solution found")
View Source
var TierMapping = map[string]core.Tier{
	"allow":           core.TierT1_Governance,
	"deny":            core.TierT1_Governance,
	"may_read":        core.TierT1_Governance,
	"may_write":       core.TierT1_Governance,
	"may_exec":        core.TierT1_Governance,
	"can_execute":     core.TierT2_Playbook,
	"can_access":      core.TierT2_Playbook,
	"requires":        core.TierT2_Playbook,
	"retry_for":       core.TierT2_Playbook,
	"validation_rule": core.TierT2_Playbook,
	"prompt_template": core.TierT2_Playbook,
	"workflow_node":   core.TierT2_Playbook,
	"workflow_edge":   core.TierT2_Playbook,
	"agent_role":      core.TierT2_Playbook,
	"role_capability": core.TierT2_Playbook,
	"task_requires":   core.TierT2_Playbook,
}

TierMapping maps predicate prefixes to governance tiers.

View Source
var TierSourceFiles = map[core.Tier]string{
	core.TierT0_Axiom:      "axioms.dl",
	core.TierT1_Governance: "governance.dl",
	core.TierT2_Playbook:   "registry.dl",
	core.TierT3_User:       "user-input.dl",
	core.TierUnknown:       "unknown",
}

TierSourceFiles maps tiers to their source files.

Functions

func Flatten

func Flatten(rootID string, input any) ([]string, error)

Flatten converts ANY dynamic structure (maps, slices of any type) into graph facts.

func FromFacts

func FromFacts[T any](rootID string, facts []string) (*T, error)

FromFacts reconstructs a struct of type T from a list of Datalog fact strings.

func LabelsToFacts

func LabelsToFacts(entityID string, labels []string) ([]string, error)

LabelsToFacts converts a slice of security label strings into Mangle Datalog facts. This is used for propagating taint information (e.g., "secret", "pii") into the policy engine.

Format:

	label("label_value")
 Note: In v2.0, we simplified this to just the label, as context is implied by the execution scope.
 Wait, the original was has_label(ID, Label). The instruction says `label(Tag)`.
 Usually context injection like `label(Tag)` means `label(Tag)` is a fact about the current context.
 But `LabelsToFacts` takes an EntityID.
 If I change it to `label(Tag)`, I lose the EntityID association unless `label` is arity 1.
 The instruction says `Decl label(Tag).`. Arity 1.
 So it seems we are moving to context-implicit predicates for the current entity?
 Or maybe `label(Tag)` is just for the current input?
 The `Authorize` function checks `deny(Req)`. Rules like `deny(Req) :- label("secret").` work if `label` is global/contextual.
 So I will produce `label("val")` instead of `has_label("id", "val")`.

Parameters:

  • entityID: The unique identifier for the entity. (Ignored in v2 vocabulary for label, but kept for API compat)
  • labels: A slice of security label strings.

Returns:

  • A slice of Datalog fact strings.
  • An error if conversion fails (unlikely, mostly wrapper around string formatting).

func ToFacts

func ToFacts(id string, input any) ([]string, error)

ToFacts converts a Go data structure into Mangle Datalog facts. It is the entry point for turning runtime objects into logic predicates.

Types

type EvaluateResult

type EvaluateResult struct {
	// Matched indicates whether the rule's head predicate was derived (i.e., the rule triggered).
	Matched bool
	// EntityID is the unique identifier of the entity that was evaluated.
	EntityID string
	// RuleHead is the name of the predicate that was checked (e.g., "deny").
	RuleHead string
}

EvaluateResult encapsulates the outcome of a rule evaluation.

type Evaluator

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

Evaluator provides capabilities for evaluating a single Datalog rule against a Go struct. It is primarily used for ad-hoc rule checking or dynamic policy evaluation where a full rule set management overhead is not required.

func NewEvaluator

func NewEvaluator(rule string) (*Evaluator, error)

NewEvaluator creates a new Evaluator instance from a Datalog rule string. The rule must be a valid Datalog clause (e.g., "deny(Req) :- ...").

Parameters:

  • rule: The Datalog rule string to parse and prepare.

Returns:

  • A pointer to a configured Evaluator, or an error if the rule is invalid.

func (*Evaluator) Evaluate

func (e *Evaluator) Evaluate(entityID string, entity any) (EvaluateResult, error)

Evaluate executes the configured Datalog rule against a provided Go struct. It automatically converts the struct fields into Datalog facts using reflection.

Parameters:

  • entityID: A unique string identifier for the entity (e.g., request ID).
  • entity: The Go struct to evaluate. Fields can be customized with `mangle` struct tags.

Returns:

  • An EvaluateResult indicating whether the rule matched, or an error if evaluation failed.

type ExternalPredicate

type ExternalPredicate func(ctx context.Context, inputs []any) ([][]any, error)

ExternalPredicate is a simple function type for external predicates. It takes input values and returns output values or an error.

type ExternalPredicateRegistry

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

ExternalPredicateRegistry holds external predicates that can be called from Datalog rules.

func NewExternalPredicateRegistry

func NewExternalPredicateRegistry() *ExternalPredicateRegistry

NewExternalPredicateRegistry creates a new registry for external predicates.

func (*ExternalPredicateRegistry) Count

func (r *ExternalPredicateRegistry) Count() int

Count returns the number of registered external predicates.

func (*ExternalPredicateRegistry) Get

Get retrieves an external predicate by name.

func (*ExternalPredicateRegistry) List

List returns all registered external predicates keyed by name.

func (*ExternalPredicateRegistry) Register

Register adds an external predicate to the registry. Arity is determined from the Datalog policy at load time.

type FactIndex

type FactIndex map[string]map[string][]string

FactIndex organizes facts for O(1) lookup during reconstruction. Map: SubjectID -> Predicate/Key -> []Value

type GherkinCompiler

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

GherkinCompiler transforms Gherkin feature files into Datalog rules.

func NewGherkinCompiler

func NewGherkinCompiler() *GherkinCompiler

NewGherkinCompiler creates a new compiler with the standard step registry.

func NewGherkinCompilerWithRegistry

func NewGherkinCompilerWithRegistry(registry *StepRegistry) *GherkinCompiler

NewGherkinCompilerWithRegistry creates a compiler with a custom registry.

func (*GherkinCompiler) Compile

func (c *GherkinCompiler) Compile(feature *parse.Feature) (string, error)

Compile transforms a parsed Feature into Datalog rules. Returns the complete Datalog program as a string.

func (*GherkinCompiler) CompileFromString

func (c *GherkinCompiler) CompileFromString(content string) (string, error)

CompileFromString parses and compiles a Gherkin feature string.

type MangleRuntime

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

MangleRuntime encapsulates the Google Mangle Datalog engine.

func NewMangleRuntime

func NewMangleRuntime() *MangleRuntime

NewMangleRuntime initializes a new, empty MangleRuntime.

func (*MangleRuntime) AddEternalFact

func (r *MangleRuntime) AddEternalFact(factString string) error

AddEternalFact adds a fact that's always true (no temporal bounds).

func (*MangleRuntime) AddPolicy

func (r *MangleRuntime) AddPolicy(source string) error

AddPolicy adds new rules to the existing program state (Incremental Loading).

func (*MangleRuntime) AddTemporalFact

func (r *MangleRuntime) AddTemporalFact(factString string, start, end time.Time) error

AddTemporalFact adds a fact with a time interval. The fact is valid during the specified time range.

func (*MangleRuntime) AddTemporalFactAt

func (r *MangleRuntime) AddTemporalFactAt(factString string, at time.Time) error

AddTemporalFactAt adds a fact valid at a specific point in time.

func (*MangleRuntime) AddTemporalFactInFuture

func (r *MangleRuntime) AddTemporalFactInFuture(factString string, duration time.Duration) error

AddTemporalFactInFuture adds a fact that will be true for a duration in the future. The fact starts at the evaluation time if set, otherwise starts at now.

func (*MangleRuntime) AddTemporalFactInPast

func (r *MangleRuntime) AddTemporalFactInPast(factString string, duration time.Duration) error

AddTemporalFactInPast adds a fact that was true for a duration in the past. The fact ends at the evaluation time if set, otherwise ends at now.

func (*MangleRuntime) ContainsTemporalFact

func (r *MangleRuntime) ContainsTemporalFact(factString string) (bool, error)

ContainsTemporalFact checks if a fact is valid at the evaluation time.

func (*MangleRuntime) EnableTemporal

func (r *MangleRuntime) EnableTemporal()

EnableTemporal enables temporal reasoning support. This must be called before loading any policies.

func (*MangleRuntime) ExecuteQuery

func (r *MangleRuntime) ExecuteQuery(ctx context.Context, facts []ast.Atom, queryStr string) (bool, error)

ExecuteQuery runs a boolean Datalog query.

func (*MangleRuntime) ExternalPredicates

func (r *MangleRuntime) ExternalPredicates() *ExternalPredicateRegistry

ExternalPredicates returns the external predicate registry for inspection.

func (*MangleRuntime) GetEvaluationTime

func (r *MangleRuntime) GetEvaluationTime() time.Time

GetEvaluationTime returns the current evaluation time.

func (*MangleRuntime) GetTemporalStore

func (r *MangleRuntime) GetTemporalStore() *factstore.TemporalStore

GetTemporalStore returns the temporal store for advanced operations.

func (*MangleRuntime) IsTemporalEnabled

func (r *MangleRuntime) IsTemporalEnabled() bool

IsTemporalEnabled returns whether temporal reasoning is enabled.

func (*MangleRuntime) Load

func (r *MangleRuntime) Load(path string) error

Load loads Datalog rules and facts from the specified path. CRITICAL CHANGE: This REPLACES the current program state.

func (*MangleRuntime) LoadFacts

func (r *MangleRuntime) LoadFacts(facts []string) error

LoadFacts injects a list of raw Datalog fact strings into the runtime's base knowledge.

func (*MangleRuntime) LoadFromSource

func (r *MangleRuntime) LoadFromSource(source string) error

LoadFromSource parses and loads a full Datalog program from a string. REPLACES current state.

Unlike AddPolicy, this path scans the external-predicate registry and auto-emits the matching `Decl ... external()` declarations. It also implicitly merges the Manglekit standard library (std.dl) so callers do not have to re-declare meta/2, triple/3, halt/2, etc.

The std.dl merge is idempotent: if the caller's source already declares a predicate with the same symbol and arity as one in std.dl (e.g. the caller explicitly wants to mark a predicate as `Decl ... external()`), the std.dl declaration for that predicate is skipped. This avoids the "cannot redeclare" error that would otherwise reject otherwise-valid policies.

func (*MangleRuntime) LoadFromString

func (r *MangleRuntime) LoadFromString(rule string) error

LoadFromString parses and loads a full Datalog program provided as a string. IMPORTANT: This REPLACES the current program state.

func (*MangleRuntime) QueryTemporalFactsAt

func (r *MangleRuntime) QueryTemporalFactsAt(factPattern string, at time.Time) ([]string, error)

QueryTemporalFactsAt queries facts that are valid at a specific time.

func (*MangleRuntime) QueryTemporalFactsDuring

func (r *MangleRuntime) QueryTemporalFactsDuring(factPattern string, start, end time.Time) ([]string, error)

QueryTemporalFactsDuring queries facts that are valid during a time interval.

func (*MangleRuntime) QueryWithSolutions

func (r *MangleRuntime) QueryWithSolutions(ctx context.Context, facts []ast.Atom, queryStr string, onSolution func(map[string]any) error) error

QueryWithSolutions executes a query and invokes callback for solutions.

func (*MangleRuntime) RegisterExternalPredicate

func (r *MangleRuntime) RegisterExternalPredicate(name string, fn ExternalPredicate) error

RegisterExternalPredicate adds an external predicate that can be called from Datalog rules. The predicate can then be used in policies like:

http_get(URL, Status) :- ...

When the predicate is called, the external function receives the input arguments and returns output values that are added as facts to the engine.

Parameters:

  • name: The predicate name (e.g., "http_get", "time_now")
  • fn: The function to call

Returns an error if the predicate name is empty or the function is nil.

func (*MangleRuntime) SetEvaluationTime

func (r *MangleRuntime) SetEvaluationTime(t time.Time)

SetEvaluationTime sets the evaluation time for temporal queries. This is the "now" time used when evaluating temporal predicates like <-[0d, 30d].

type PolicyEngine

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

PolicyEngine is the core decision-making component of Manglekit. It orchestrates the loading of policies, maintaining the Datalog runtime, and executing authorization (Pre-Check) and validation (Post-Check) logic. It also integrates with observability (Tracing/Logging) to provide transparent governance.

func New

func New() (*PolicyEngine, error)

New creates a new PolicyEngine with default no-op observability. This is suitable for basic usage where tracing and structured logging are not required.

Returns:

  • A pointer to a new PolicyEngine instance.

func NewWithObservability

func NewWithObservability(tracer core.Tracer, logger core.Logger) (*PolicyEngine, error)

NewWithObservability creates a new PolicyEngine with both tracing and logging enabled. This is the recommended constructor for production use.

Parameters:

  • tracer: The tracer implementation (e.g., OpenTelemetry).
  • logger: The logger implementation.

Returns:

  • A pointer to a new PolicyEngine instance.

func NewWithTracer deprecated

func NewWithTracer(tracer core.Tracer) *PolicyEngine

NewWithTracer creates a new PolicyEngine with tracing enabled.

Deprecated: Use NewWithObservability instead.

Parameters:

  • tracer: The tracer implementation to use.

Returns:

  • A pointer to a new PolicyEngine instance.

func (*PolicyEngine) Assess

func (e *PolicyEngine) Assess(ctx context.Context, actionMeta core.ActionMetadata, input core.Envelope) error

Assess performs the Pre-Check phase of governance. It checks if the input is allowed to proceed based on the loaded policies. If the `infeasible(Req, Reason)` or `deny(Req)` predicate is derived, it returns `core.ErrAlignment`.

It automatically starts a tracing span (`Datalog.Assess`) and logs attributes.

Parameters:

  • ctx: The execution context.
  • actionMeta: Metadata about the action being authorized.
  • input: The input envelope containing the payload and security labels.

Returns:

  • core.ErrAlignment if blocked, or nil if allowed.

Formerly: Authorize

func (*PolicyEngine) AssessPlan

func (e *PolicyEngine) AssessPlan(ctx context.Context, input core.Envelope) (core.Decision, error)

AssessPlan implements the core.Evaluator interface. It performs a high-level assessment of the input, mapping Assess logic to a Decision. The Decision.AuditTrail is populated from the gate evaluation, carrying matched rules, tiers, latencies, and fact counts.

func (*PolicyEngine) CheckRequirement

func (e *PolicyEngine) CheckRequirement(ctx context.Context, input core.Envelope, reqName string) (bool, error)

CheckRequirement queries: requires("req_id", "capability")

func (*PolicyEngine) EvaluateSteering

func (e *PolicyEngine) EvaluateSteering(ctx context.Context, input core.Envelope) (string, map[string]string, error)

EvaluateSteering executes "Steering Policies" which determine what to do next. Unlike Assess/Reflect (which are binary Proceed/Infeasible), Steering returns decisions like "Retry" or "Route".

Logic Priority:

  1. Correction (Retry): If `retry(Hint)` is derived, we return `RETRY` with the hint.
  2. Routing (Route): If `route(Target)` is derived, we return `ROUTE` with the target.
  3. Default: `PROCEED` (Proceed as normal).

Parameters:

  • ctx: The execution context.
  • input: The input envelope.

Returns:

  • decision: The decision string (e.g., "RETRY", "ROUTE", "PROCEED").
  • metadata: A map containing steering details (e.g., {"feedback": "hint"}).
  • error: An error if evaluation fails.

func (*PolicyEngine) ExecuteQuery

func (e *PolicyEngine) ExecuteQuery(ctx context.Context, facts []ast.Atom, queryStr string) (bool, error)

ExecuteQuery executes a raw Datalog query against the current program state. It wraps the underlying runtime execution with observability (tracing).

Parameters:

  • ctx: The execution context.
  • facts: Temporary facts to include in this specific query execution.
  • queryStr: The Datalog query atom.

Returns:

  • true if derived, false otherwise.
  • error if execution fails.

func (*PolicyEngine) ExternalPredicateRegistry

func (e *PolicyEngine) ExternalPredicateRegistry() *ExternalPredicateRegistry

ExternalPredicateRegistry returns the external predicate registry for inspection.

func (*PolicyEngine) ExtractActionArguments

func (e *PolicyEngine) ExtractActionArguments(ctx context.Context, input core.Envelope, actionName string) (map[string]interface{}, error)

ExtractActionArguments queries the engine for action arguments from Datalog bindings. This enables the PolicyEngine to dynamically extract arguments from Datalog rules and populate the ActionEnvelope.Arguments.

Datalog pattern: suggested_action(ActionName, [key1: value1, key2: value2]) Or: action_args(ActionName, Key, Value)

Parameters:

  • ctx: The execution context.
  • input: The input envelope.
  • actionName: The action name to extract arguments for.

Returns:

  • map[string]interface{} of extracted arguments.
  • error if extraction fails.

func (*PolicyEngine) GetActionConfig

func (e *PolicyEngine) GetActionConfig(ctx context.Context, input core.Envelope) (map[string]string, error)

GetActionConfig queries the engine for dynamic configuration parameters. It executes the query `action_config(Key, Value)` and returns a map of results.

Parameters:

  • ctx: The execution context.
  • input: The input envelope.

Returns:

  • A map of configuration keys and values.
  • An error if execution fails.

func (*PolicyEngine) LoadFacts

func (e *PolicyEngine) LoadFacts(facts []string) error

LoadFacts injects a list of raw Datalog fact strings into the runtime's base knowledge. This allows adding dynamic context or configuration at runtime (e.g., feature flags).

Parameters:

  • facts: A slice of Datalog fact strings.

Returns:

  • An error if parsing or evaluation fails.

func (*PolicyEngine) LoadFromSource

func (e *PolicyEngine) LoadFromSource(ctx context.Context, source string) error

LoadFromSource loads a Datalog program from a raw string, replacing any existing program state. Unlike LoadPolicy (which routes to AddPolicy), this path also scans the external-predicate registry and auto-emits the matching `Decl ... external()` declarations. Use this when the policy references external predicates that were registered via RegisterExternalPredicate.

func (*PolicyEngine) LoadGherkinPolicy

func (e *PolicyEngine) LoadGherkinPolicy(ctx context.Context, featureContent string) error

LoadGherkinPolicy loads a Gherkin feature file and compiles it to Datalog. This enables BDD-style policy definitions using natural language.

Parameters:

  • ctx: The execution context.
  • featureContent: The Gherkin feature file content.

Returns:

  • An error if parsing, compilation, or loading fails.

func (*PolicyEngine) LoadPolicy

func (e *PolicyEngine) LoadPolicy(ctx context.Context, policy string) error

LoadPolicy loads policy rules from a raw Datalog string. This decouples the engine from file I/O.

Parameters:

  • ctx: The execution context (unused in current implementation but required by interface).
  • policy: The Datalog rules as a string.

Returns:

  • An error if parsing or loading fails.

func (*PolicyEngine) Logger

func (e *PolicyEngine) Logger() core.Logger

Logger returns the engine's configured Logger instance. This allows other components (like SupervisedAction) to reuse the engine's logger.

Returns:

  • The configured Logger, or a NopLogger if none was set.

func (*PolicyEngine) Query

func (e *PolicyEngine) Query(ctx context.Context, facts []string, queryStr string) ([]map[string]string, error)

Query executes a Datalog query and returns all matching solutions. Each solution is a map where keys are variable names (e.g., "Action") and values are stringified constants.

Parameters:

  • ctx: The execution context.
  • facts: Temporary facts (strings) to include.
  • queryStr: The Datalog query with variables (e.g., 'plan_step(Action, Order)').

Returns:

  • A list of solution maps.
  • An error if execution fails.

func (*PolicyEngine) QueryWithAudit

func (e *PolicyEngine) QueryWithAudit(ctx context.Context, facts []string, queryStr string) (*QueryWithAuditResult, error)

QueryWithAudit executes a Datalog query and returns results along with an audit trail. The audit trail explains which rules were matched and from which tier they originated.

func (*PolicyEngine) RecordLineage

func (e *PolicyEngine) RecordLineage(ctx context.Context, childID, parentID string)

RecordLineage records a data lineage relationship between a child and a parent. It emits a span event if tracing is enabled.

func (*PolicyEngine) Reflect

func (e *PolicyEngine) Reflect(ctx context.Context, actionMeta core.ActionMetadata, output core.Envelope) (core.Envelope, error)

Reflect performs the Post-Check phase of governance. It checks if the output is allowed to be returned to the caller. If the `infeasible(Output, Reason)` predicate is derived, it returns `core.ErrAlignment`.

It automatically starts a tracing span (`Datalog.Reflect`) and logs attributes.

Parameters:

  • ctx: The execution context.
  • actionMeta: Metadata about the action being validated.
  • output: The output envelope containing the result.

Returns:

  • The validated envelope (potentially modified, though currently pass-through), or an error.

Formerly: Validate

func (*PolicyEngine) RegisterAction

func (e *PolicyEngine) RegisterAction(meta core.ActionMetadata) error

RegisterAction injects metadata about a registered action into the Datalog runtime. It generates facts that describe the action's interface, enabling the Planner to reason about it.

Generated Facts:

  • action("name")
  • has_input("name", "InputType")
  • has_output("name", "OutputType")

Parameters:

  • meta: The metadata of the action.

Returns:

  • An error if fact loading fails.

func (*PolicyEngine) RegisterExternalPredicate

func (e *PolicyEngine) RegisterExternalPredicate(name string, fn func(ctx context.Context, inputs []any) ([][]any, error)) error

RegisterExternalPredicate adds an external predicate to the policy engine. External predicates allow Datalog rules to call Go functions for operations like HTTP requests, database lookups, time checks, etc.

Example usage:

engine.RegisterExternalPredicate("http_get", func(ctx context.Context, inputs []any) ([][]any, error) {
    url := inputs[0].(string)
    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    return [][]any{{resp.StatusCode}}, nil
})

Then use in policy:

http_allowed(URL) :- http_get(URL, Status), Status >= 200, Status < 300.

Note: External predicates are evaluated at runtime and can introduce non-determinism. Use with caution in security-critical policies.

func (*PolicyEngine) Runtime

func (e *PolicyEngine) Runtime() *MangleRuntime

Runtime returns the underlying MangleRuntime for advanced usage. Use with caution - directly manipulating the runtime bypasses PolicyEngine safeguards.

func (*PolicyEngine) WithQueryTimeout

func (e *PolicyEngine) WithQueryTimeout(timeout time.Duration) *PolicyEngine

WithQueryTimeout sets the maximum duration for a single query execution. If a query exceeds this timeout, it returns context.DeadlineExceeded. A zero or negative duration means no timeout (unlimited).

type QueryWithAuditResult

type QueryWithAuditResult struct {
	Results    []map[string]string
	AuditTrail *core.AuditTrail
}

QueryWithAuditResult contains the query results along with the audit trail.

type StepDefinition

type StepDefinition struct {
	Pattern  *regexp.Regexp
	Template string // Datalog template with {placeholder} syntax
	StepType parse.StepType
}

StepDefinition defines a mapping from a Gherkin step pattern to a Datalog template.

type StepRegistry

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

StepRegistry holds all registered step definitions.

func NewStepRegistry

func NewStepRegistry() *StepRegistry

NewStepRegistry creates a new registry with standard step definitions.

func (*StepRegistry) GenerateDatalog

func (r *StepRegistry) GenerateDatalog(step parse.Step, expectedType parse.StepType) (string, error)

GenerateDatalog generates a Datalog fragment for a step.

func (*StepRegistry) Match

func (r *StepRegistry) Match(step parse.Step, expectedType parse.StepType) (*StepDefinition, map[string]string, error)

Match attempts to match a step against registered definitions. Returns the matched definition and extracted parameters.

func (*StepRegistry) Register

func (r *StepRegistry) Register(pattern, template string, stepType parse.StepType) error

Register adds a new step definition to the registry. Pattern should be a regex with capturing groups. Template should use {name} placeholders that will be replaced with captured values.

func (*StepRegistry) Substitute

func (r *StepRegistry) Substitute(template string, params map[string]string) string

Substitute replaces placeholders in a template with actual values.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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