Documentation
¶
Index ¶
- Constants
- func CheckStaticBounds(f Flow, b *Budget) error
- func EvalCondition(c Condition, ctx map[string]any, b *Budget, depth int) (bool, error)
- func GenSignerCert(dir string) (certPath, keyPath string, cert *x509.Certificate, err error)
- func GenSignerCertWithCapabilities(dir string, caps []pki.Capability) (certPath, keyPath string, cert *x509.Certificate, err error)
- func GenSignerCertWithGrant(dir string, caps, constraints []pki.Capability) (certPath, keyPath string, cert *x509.Certificate, err error)
- func GenerateSelectSQL(raw json.RawMessage) (string, []any, error)
- func MapHTTPRequest(ctx *pki.PluginContext) map[string]any
- func PublishManifestJSON(m *PublishManifest) (string, error)
- func RegisterRulePluginsFromDir(reg *pki.PluginRegistry, dir string, trustRoots []*x509.Certificate, ...) ([]string, error)
- func RuleWithinSignerGrant(rule *Rule, signer *x509.Certificate) error
- func RunFlow(f Flow, ctx *FlowContext, b *Budget) error
- func ValidateStructure(r *Rule) error
- type Budget
- type BudgetDefaults
- type BudgetError
- type BudgetKind
- type Condition
- type Constraint
- type Decision
- type DecisionInput
- type Flow
- type FlowContext
- type HTTPGateway
- type OpHandler
- type PhaseTwo
- type PublishManifest
- type Rule
- type RuleExecutor
- type RulePlugin
- type RuleVersion
- type SQLExecutor
- type SchemePublish
- type Step
Constants ¶
const ( DefaultMaxSteps = 10000 DefaultMaxDepth = 64 DefaultMaxNesting = 64 )
Default budgets (to be published with the scheme spec; see docs/database-scheme-design.md §7).
const ( MaxStepsCeiling = 10000 MaxDepthCeiling = 64 MaxNestingCeiling = 64 )
Published ceilings (see budget-defaults.json). Implementations MUST NOT relax these values; a file that asks for more is rejected.
Variables ¶
This section is empty.
Functions ¶
func CheckStaticBounds ¶
CheckStaticBounds walks a flow BEFORE execution and enforces a zero-cost structural rule: nesting depth must fit the budget. Loops and retries were removed from the execution language (2026-09-10), so a flow is a finite tree of op / if / seq: termination is structural and a single authorization can trigger at most one execution of each operation (no amplification factor).
func EvalCondition ¶
EvalCondition evaluates a condition against a context map with a budget. Depth is tracked to prevent nesting-based abuse.
func GenSignerCert ¶
func GenSignerCert(dir string) (certPath, keyPath string, cert *x509.Certificate, err error)
GenSignerCert generates a self-signed rule-signer certificate and key.
This is a compatibility re-export. The implementation lives in internal/rulesigner; the wrapper exists because moving an *exported* symbol into internal/ silently breaks every downstream module — Go forbids importing internal/ from outside this module, so consumers such as the gateway module's end-to-end fixtures (http/ruleplugins_test.go, e2e_real_test.go, e2e_matrix_test.go, gateway_rules_test.go) stopped compiling.
Callers that need the AIC-carrying variants (so that RuleWithinSignerGrant can pass) should use the internal helper from inside this module.
func GenSignerCertWithCapabilities ¶ added in v0.2.0
func GenSignerCertWithCapabilities(dir string, caps []pki.Capability) (certPath, keyPath string, cert *x509.Certificate, err error)
GenSignerCertWithCapabilities generates a signer certificate that carries an AIC extension whose grant covers caps.
Rule *publication* requires this: the loader enforces RuleWithinSignerGrant, so a rule signed by a certificate without an AIC extension (the plain GenSignerCert above) is refused with "signer certificate has no AIC extension". Downstream modules — e.g. the gateway module's end-to-end fixtures — need this exported variant to build signers that can actually publish rules.
func GenSignerCertWithGrant ¶ added in v0.2.0
func GenSignerCertWithGrant(dir string, caps, constraints []pki.Capability) (certPath, keyPath string, cert *x509.Certificate, err error)
GenSignerCertWithGrant is GenSignerCertWithCapabilities plus constraints.
func GenerateSelectSQL ¶
func GenerateSelectSQL(raw json.RawMessage) (string, []any, error)
GenerateSelectSQL renders the MySQL SQL for a database-v1 query:SELECT rule (v1 contract: exactly one table). The params must already have passed Validate (rule.go); this function is the "translator" that turns the structured contract into a PARAMETERIZED statement.
All values are returned as placeholders (?) plus args, in statement order: no value is ever spliced into SQL text. Identifiers (table/column names) are still quoted with backticks, and are validated against the rule's declared tables/columns before rendering.
func MapHTTPRequest ¶
func MapHTTPRequest(ctx *pki.PluginContext) map[string]any
MapHTTPRequest converts gateway-core PluginContext facts (including the optional HTTP request fields) into the request map consumed by rule conditions: request.method / request.path / request.query / request.headers plus target/client_cn/agent_id/roles.
HTTP-facing gateways populate ctx.Method/Path/Query/Headers; the TCP admission path only provides Target/ClientCN/Roles/AgentId.
func PublishManifestJSON ¶
func PublishManifestJSON(m *PublishManifest) (string, error)
PublishManifestJSON renders the manifest for output.
func RegisterRulePluginsFromDir ¶
func RegisterRulePluginsFromDir(reg *pki.PluginRegistry, dir string, trustRoots []*x509.Certificate, handler OpHandler, sreg *register.Registry) ([]string, error)
RegisterRulePluginsFromDir loads signed rules from a published rule directory (outDir/<scheme>/default.json [+ .p7s], as produced by PublishRules) and registers one RulePlugin per scheme into reg. Returns the registered scheme list. Any signature or validation failure aborts the whole registration (fail-closed). reg is the gateway registry; sreg is the CLC scheme registry used by Rule.Validate (fail closed, must not be nil).
func RuleWithinSignerGrant ¶ added in v0.2.0
func RuleWithinSignerGrant(rule *Rule, signer *x509.Certificate) error
RuleWithinSignerGrant enforces the PUBLICATION BOUNDARY of a signed rule: the capability a rule declares MUST be covered by the signer's own AIC grant (CLC-v1 entailment, semantics.Entails), and every constraint the rule declares MUST also be declared by the signer.
Without this check a holder of any trusted signing certificate could publish a rule that exceeds its own authority. The check is fail-closed: a signer without an AIC extension, or without a covering capability, is rejected.
func RunFlow ¶
func RunFlow(f Flow, ctx *FlowContext, b *Budget) error
RunFlow executes a flow with the given budget.
func ValidateStructure ¶
ValidateStructure performs schema-level validation of a rule: field formats, condition operators, flow step kinds and nesting.
Types ¶
type Budget ¶
type Budget struct {
MaxSteps int64
MaxDepth int
MaxNesting int
Deadline time.Time
// contains filtered or unexported fields
}
Budget enforces the execution budget for conditions and flows. Since loops and retries were removed (2026-09-10) a flow is a finite tree, so the budget is a defence-in-depth guard rather than the termination argument.
func BudgetFromDefaults ¶
func BudgetFromDefaults(d *BudgetDefaults) *Budget
BudgetFromDefaults builds a Budget from published defaults.
func NewBudget ¶
func NewBudget() *Budget
NewBudget returns a budget with the specification defaults.
type BudgetDefaults ¶
type BudgetDefaults struct {
MaxSteps int `json:"max_steps"`
MaxDepth int `json:"max_depth"`
MaxNesting int `json:"max_nesting"`
}
BudgetDefaults is the published execution budget, distributed with the scheme spec (see budget-defaults.json and docs/database-scheme-design.md §7). Implementations MUST NOT relax these values.
func LoadBudgetDefaults ¶
func LoadBudgetDefaults(path string) (*BudgetDefaults, error)
LoadBudgetDefaults reads a published budget-defaults.json.
type BudgetError ¶
type BudgetError struct {
Kind BudgetKind
Used int64
Max int64
}
BudgetError is returned when an execution budget is exceeded.
func (*BudgetError) Error ¶
func (e *BudgetError) Error() string
type BudgetKind ¶
type BudgetKind int
BudgetKind identifies which budget was exceeded.
const ( KindSteps BudgetKind = iota KindDepth KindNesting KindTimeout )
func (BudgetKind) String ¶
func (k BudgetKind) String() string
type Condition ¶
type Condition struct {
Op string `json:"op"`
Path string `json:"path,omitempty"`
Value any `json:"value,omitempty"`
Window []string `json:"window,omitempty"` // between
Items []Condition `json:"items,omitempty"` // and / or / not
}
Condition is the structured condition AST (the "mini language"). Leaf ops compare a resolved path against a value; and/or/not combine sub-conditions.
type Constraint ¶
type Constraint struct {
Scheme string `json:"scheme"`
ID string `json:"id"`
Params json.RawMessage `json:"params,omitempty"`
}
Constraint references a registered constraint type.
type DecisionInput ¶
type DecisionInput struct {
AgentID string
PrincipalID string
Mode string
EffectiveCaps []string
Request map[string]any
Now time.Time
}
DecisionInput mirrors the facts a gateway phase-two plugin receives after AIC validation: EffectiveCaps (P∩C) plus request context (see gateway-core AdmissionResult.EffectiveCaps).
type Flow ¶
type Flow struct {
Steps []Step `json:"steps"`
}
Flow is the minimal workflow AST (Python/C-style flow control).
type FlowContext ¶
FlowContext carries task-local variables, the request facts, and the operation handler (the gateway's fixed capability executor).
type HTTPGateway ¶
type HTTPGateway struct {
// contains filtered or unexported fields
}
HTTPGateway is the reference "rule -> gateway -> mysql-api" chain: it simulates the gateway admission path (mTLS identity from the verified peer certificate of the terminating TLS connection), runs the phase-two rule plugin, generates SQL from the rule params, and executes it against the database.
func NewHTTPGateway ¶
func NewHTTPGateway(plugins map[string]*RulePlugin, exec SQLExecutor) *HTTPGateway
NewHTTPGateway builds a gateway with per-user rules and an executor.
func (*HTTPGateway) Handler ¶
func (g *HTTPGateway) Handler() http.Handler
Handler exposes the HTTP handler (for httptest or a real server).
type OpHandler ¶
OpHandler executes a named operation (e.g. "db:select"). The returned map is merged into task variables.
type PhaseTwo ¶
type PhaseTwo interface {
Decide(in DecisionInput) (*Decision, error)
}
PhaseTwo is the policy-executor contract the gateway phase-two plugin slot expects (per-scheme routing after EffectiveCaps).
type PublishManifest ¶
type PublishManifest struct {
Schemes map[string]SchemePublish `json:"schemes"`
}
PublishManifest is the publication manifest.
func PublishRules ¶
func PublishRules(rulesDir, outDir, certPath, keyPath string, reg *register.Registry) (*PublishManifest, error)
PublishRules publishes rule files from rulesDir into outDir:
rulesDir/<scheme>/v<maj>.<min>.json
Each rule is validated against the registry's parameter contract (Rule.Validate, the same check the claims path uses -- not just structure) and PKCS#7 signed. default.json is published as a byte-identical copy of the highest minor version, so its .p7s detached signature stays valid without re-signing. certPath/keyPath are the signer certificate/key (PEM); reg supplies the scheme definitions the rule must satisfy (fail closed, never nil).
type Rule ¶
type Rule struct {
RuleID string `json:"rule_id"`
Version string `json:"version"`
Scheme string `json:"scheme"`
Capability string `json:"capability"`
Params json.RawMessage `json:"params"`
Conditions *Condition `json:"conditions,omitempty"`
Constraints []Constraint `json:"constraints,omitempty"`
Flow *Flow `json:"flow,omitempty"`
}
Rule is the signed rule file format (draft, see docs/database-scheme-design.md §8).
func LoadRuleBytes ¶
LoadRuleBytes parses a rule from JSON bytes.
Unknown fields are rejected (fail-closed): a misspelled key such as "condtions" would otherwise be dropped silently and the rule would load — and execute — without the constraint the author meant to write. Rules are machine-generated as often as hand-written, so the loader must not be lenient about field names.
type RuleExecutor ¶
RuleExecutor binds a signed rule to the phase-two contract.
func (*RuleExecutor) Decide ¶
func (e *RuleExecutor) Decide(in DecisionInput) (*Decision, error)
Decide validates the rule structure, runs the static bounds pre-check, evaluates the conditions against the request, and runs the flow. Authorization itself stays in the AIC layer; this executor only implements the rule's conditions and orchestration.
type RulePlugin ¶
type RulePlugin struct {
// contains filtered or unexported fields
}
RulePlugin adapts a signed rule to the gateway-core phase-two plugin slot (CapabilityPlugin). The admission pipeline calls Execute once per effective capability whose scheme matches Scheme(); a PluginDeny or error denies the connection (fail-closed).
func LoadRulePlugin ¶
func LoadRulePlugin(rulePath string, trustRoots []*x509.Certificate, handler OpHandler, reg *register.Registry) (*RulePlugin, error)
LoadRulePlugin loads a published (PKCS#7 signed) rule file and builds the gateway phase-two plugin for it. Signature verification and registry validation are mandatory (fail-closed): a tampered, unsigned, or parameters-contract-violating rule is rejected. A fresh execution budget is created per plugin so that counters are never shared across executions.
func NewRulePlugin ¶
func NewRulePlugin(scheme string, rule *Rule, budget *Budget, handler OpHandler) *RulePlugin
NewRulePlugin builds a phase-two plugin executing rule for scheme.
func (*RulePlugin) Execute ¶
func (p *RulePlugin) Execute(cap *pki.Capability, ctx *pki.PluginContext) (*pki.PluginResult, error)
Execute maps gateway-core PluginContext facts into a DecisionInput and runs the rule executor (structure -> static bounds -> conditions -> flow). Authorization stays in the AIC layer; this implements the rule's conditions and orchestration only.
func (*RulePlugin) Scheme ¶
func (p *RulePlugin) Scheme() string
Scheme returns the capability scheme this plugin serves.
type RuleVersion ¶
type RuleVersion struct{ Major, Minor int }
RuleVersion is a parsed v<major>.<minor>.json version.
type SQLExecutor ¶
SQLExecutor runs a generated SQL statement and returns rows as JSON objects. The context carries the request's deadline: implementations MUST honour it so a slow/stalled query cannot outlive its HTTP request (audit 2026-09-16, R9). The real implementation talks to MySQL; tests inject a fake.
func DBExecutor ¶
func DBExecutor(db *sql.DB) SQLExecutor
DBExecutor adapts a *sql.DB to SQLExecutor (real MySQL/MariaDB). It enforces a bounded deadline on every query, honouring (but never exceeding) the caller's context.
type SchemePublish ¶
SchemePublish describes one published rule scheme.
type Step ¶
type Step struct {
Name string `json:"name,omitempty"`
Kind string `json:"kind"`
Op string `json:"op,omitempty"`
Condition *Condition `json:"condition,omitempty"`
Then []Step `json:"then,omitempty"`
Else []Step `json:"else,omitempty"`
Steps []Step `json:"steps,omitempty"`
}
Step kinds: op | if | seq