Documentation
¶
Overview ¶
Package rules is wowapi's rule/configuration engine: modules register rule points (a key, a JSON-Schema'd value, a default, allowed scopes, and whether changes require approval); values are stored as versioned rows with temporal validity; and resolution picks the most specific active value for a (tenant, org, at) — org-ancestry → tenant → platform → code default. Versions are immutable (never mutated, only superseded), so any historical `at` resolves deterministically. Contract: blueprint 02 §2.
Rule points are the ONLY sanctioned place for values that must change without a deploy (feature flags, tenant overrides); framework config holds only their platform defaults (12 §6).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type OrgAncestry ¶
type OrgAncestry func(ctx context.Context, db database.TenantDB, orgID uuid.UUID) ([]uuid.UUID, error)
OrgAncestry resolves an org's ancestor chain (self-first) so the resolver can walk org scope upward. Implemented against the DB by the caller-provided func so kernel/rules need not import the org store.
type Point ¶
type Point struct {
Key string
Module string
ValueSchema json.RawMessage // JSON Schema (validated at write + resolve)
Default json.RawMessage // compiled default value
AllowedScopes []ScopeKind
RequiresApproval bool
Description string
}
Point is a registered rule point: the schema + default + policy for a key.
type Proposal ¶
type Proposal struct {
Key string
Scope ScopeKind
ScopeID uuid.UUID // org id for org scope; zero otherwise
Value json.RawMessage
EffectiveFrom time.Time // zero → now
}
Proposal is a requested rule value change at a scope.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry collects rule points during module registration; it is synced to rule_definitions at boot and consulted by the resolver for defaults + policy.
type Resolved ¶
type Resolved struct {
Key string
Value json.RawMessage
Scope ScopeKind // scope the winning version was set at (or "" for the code default)
VersionID uuid.UUID // zero when the code default won
IsDefault bool
}
Resolved is a rule value plus provenance.
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver resolves rule values. It runs on the caller's TenantDB (one snapshot), reads active versions, and falls back to the registered default.
func NewResolver ¶
func NewResolver(reg *Registry, ancestry OrgAncestry) *Resolver
NewResolver builds a resolver over the rule registry. ancestry may be nil (org-scope resolution then falls back to tenant/platform/default).
func (*Resolver) Resolve ¶
func (r *Resolver) Resolve(ctx context.Context, db database.TenantDB, key string, org uuid.UUID, at time.Time) (Resolved, error)
Resolve returns the effective value of key for (tenant, org, at): the most specific active version wins — org-ancestry (nearest first) → tenant → platform → code default. Versions are immutable, so any historical `at` resolves deterministically (blueprint 02 §2.2). An unregistered key is a programming error.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists rule versions. Writes run on the caller's TenantDB (draft proposals as app_rt) or a platform connection (activation as app_platform).
func (*Store) Activate ¶
func (s *Store) Activate(ctx context.Context, db database.DBTX, versionID, approvedBy uuid.UUID) error
Activate approves a draft version: it supersedes any active version at the same scope and marks the draft active, recording the approver — all in one tx. Runs with platform privilege (rule activation is a kernel/platform concern). Returns an error if the version is not in draft/pending.
func (*Store) Propose ¶
Propose inserts a DRAFT rule version in the caller's tenant tx (app_rt may INSERT). A draft never resolves — it must be Activate'd (a platform/kernel operation, app_platform) to take effect. This keeps rule ACTIVATION — which changes runtime behavior — off the module-facing app_rt role, consistent with the config-write posture (SEC-13). The RequiresApproval flag governs whether a human/workflow approval must precede Activate; the store mechanics are uniform.