# SG/Sentinel: The Rules Engine Where Rules Are Everything

**version** v0.27.58
**date** 18 May 2026
**from** Human (project lead)
**to** Architect, Developer (lead), Security, @Dev
**type** Arch brief

---

## What This Is

The fourth brief in the security-tools series, and the one that defines the heart of the edge layer: **the rules engine**. It also settles the naming question from the principles brief: **the edge layer is SG/Sentinel**: the one that guards, protects, and lets the good traffic through. The name is decided; this brief and all subsequent ones use it.

The central architectural thesis is strong and worth stating plainly: **in SG/Sentinel, rules are not something you add on top of an engine. Rules are the engine. They should be 98% of the code.** The core engine is just a small, tight, efficient machine for executing rules. Every block, every action, every behaviour, every decision is a rule. The engine without rules does nothing; the behaviour of the entire platform is determined entirely by the rules that exist at any given moment.

This brief covers the rules-as-everything principle, the tiny-core-engine consequence, the update-risk gradient, the spectrum of rule types (from deterministic-and-fast to LLM-driven-and-async), per-rule least privilege, version control per rule, and the critical principle that LLMs are used heavily to build and test rules but never run inline in production.

The voice memo identified this as the historical bottleneck: **custom rules have always been the weak point of WAFs and security products.** SG/Sentinel's answer is to make rules the entire point, designed and tested and versioned with first-class discipline, rather than an afterthought bolted onto a fixed engine.

## The Naming Is Settled: SG/Sentinel

The principles brief left the name open with several candidates. The voice memo decided: **SG/Sentinel**. The reasoning is clean: a sentinel is the one that guards and protects, that watches what passes and decides what is allowed through. It captures the role precisely: the guarding, watching, allowing-or-blocking layer at the perimeter.

All subsequent briefs in this series, and all code, use SG/Sentinel. The relationship to the existing SG/Edge compute layer is now clearer too: SG/Edge is the compute that runs workloads; SG/Sentinel is the guard that sits in front of everything. Distinct names, distinct roles, related infrastructure.

## Rules Are Everything

The core principle, stated as strongly as the voice memo stated it: **everything that happens in SG/Sentinel is defined by a rule.** Not most things. Everything.

- Every block is a rule
- Every allow is a rule
- Every log action is a rule
- Every cleanup is a rule
- Every routing decision is a rule
- Every response transformation is a rule
- Every reaction to load or attack is a rule

The consequence: **the engine itself is just a machine for executing rules.** Strip the rules away and the engine does nothing. The behaviour of SG/Sentinel at any moment is entirely a function of which rules exist and are enabled at that moment.

This is the inversion that matters. Most security products have a substantial fixed engine with rules as configuration on top. SG/Sentinel has a minimal fixed engine with rules as the entire substance. The voice memo: **"the whole thing is basically an engine to execute rules, that's it."**

The benefits of this inversion:

| Benefit | Why |
|---------|-----|
| **The core engine rarely changes** | Once the rule-execution machine works, it is stable; behaviour changes through rules |
| **Behaviour is auditable** | The full behaviour is the set of active rules; you can read it |
| **Rules compose** | Rules of rules, rule groups, handovers between rules; arbitrary composition |
| **Risk is localised** | Changing a rule is low-risk; changing the engine is high-risk; the two are cleanly separated |
| **Testing is focused** | Each rule is testable in isolation; the engine is tested once |
| **The pattern applies at every layer** | Layer 1, Layer 2, Layer 3 all run rules; the same model everywhere |

## The Tiny Core Engine

The consequence of rules-are-everything: **the core engine should be very small, very tight, very efficient, and high-privilege.** Everything else is just rule execution at lower privilege.

This mirrors the layered-Lambda model from the execution-model brief, applied recursively. Just as we have different Lambda types for different jobs, **every layer of SG/Sentinel has a tiny core engine plus a set of rules.** The core engine is the high-privilege operation; the rules are low-privilege executions within it.

The design goals for the core engine:

- **Small**: minimal code; the less there is, the less can go wrong
- **Tight**: no slack; every line justified
- **Efficient**: it runs on every request at Layer 1; performance is paramount
- **High-privilege**: it is the trusted base; rules run within the trust boundary it establishes
- **Stable**: once it works, it changes rarely

The voice memo's framing: **"the core engine should probably be, after a while, very rarely changed; it's the rules that become important."** The engineering investment goes into the engine once; thereafter the work is in rules.

This separation is also a security property. **The high-privilege core is small enough to audit thoroughly and stable enough to trust. The rules, which change constantly, run at lower privilege within the boundary the core establishes.** A buggy rule cannot do what a buggy engine could; the blast radius is contained by the privilege model.

## The Update-Risk Gradient

A direct consequence the voice memo drew out: **there is a large difference, in quality and risk terms, between updating a rule, enabling a rule, and updating the engine.**

| Operation | Risk | Frequency | Review Required |
|-----------|------|-----------|-----------------|
| **Enabling/disabling a rule** | Low | Constant | Light (the rule already exists and is tested) |
| **Updating a rule** | Medium | Frequent | Moderate (test the changed rule) |
| **Adding a new rule** | Medium | Frequent | Moderate (test the new rule in isolation) |
| **Updating the core engine** | High | Rare | Heavy (it affects everything) |

This gradient is operationally important. **Most changes are rule changes, which are low-to-medium risk and can happen constantly.** Engine changes are rare and heavily reviewed. The separation means the high-frequency activity (tuning rules) is also the low-risk activity, and the high-risk activity (engine changes) is rare.

The voice memo noted that editing and maintaining rules is not a one-time activity: **"it's something that happens all the time, every day."** The architecture must make constant rule changes safe, which the privilege model and per-rule testing enable. The de-risking comes from rules being small, single-responsibility, tested in isolation, and version-controlled.

## The Spectrum Of Rule Types

The voice memo named a spectrum of rule types, from highly deterministic to LLM-driven. This maps onto the layered-responder model from the execution-model brief.

| Rule Type | Characteristics | Layer | Example |
|-----------|-----------------|-------|---------|
| **Deterministic / fast** | Tiny, super-fast, no dependencies, single specific job | Layer 1 | Block this IP; reject this malformed header |
| **Logic** | More logic, still fast, possibly cached data | Layer 1-2 | Rate-limit this pattern; validate this request shape |
| **File-dependent (cached)** | Needs a file already cached in the function | Layer 2 | Check against an embedded allowlist |
| **File-dependent (real-time)** | Needs a file loaded at request time | Layer 2 | Check against a freshly-loaded threat list |
| **Light-LLM** | Needs a fast, cheap model (Nova) | Layer 3 (async) | Classify ambiguous traffic |
| **Complex-LLM** | Needs a full model for deep analysis | Layer 3 (async) | Analyse an attack pattern; generate new rules |

The voice memo's framing: rules go **"from the highly deterministic to the highly LLM-driven."** The fast deterministic rules are like the CloudFront Functions: light, specific, single-purpose. The LLM rules are async, out-of-line, doing analysis that informs the fast rules.

Each rule declares its requirements:

- **Does it run inline or out-of-line?** Inline rules must be fast; out-of-line rules can take time.
- **Does it need a file?** Cached (already in the function) or real-time (loaded on demand)?
- **Does it need an LLM?** None, light (Nova), or complex (full model)?
- **What does it process?** Strong input schema.
- **What does it produce?** Strong output schema.

The voice memo was emphatic about schemas: **"strong schemas in and strong schemas out."** Every rule has a declared, validated input and output contract. This is what makes rules composable, testable, and safe.

## Per-Rule Least Privilege

A principle that connects directly to the TUI API IAM work from yesterday: **each rule asks for exactly what it needs and is given only that.**

The voice memo: **"each rule should ask what it needs, and should only be given that. Not every rule needs access to all the data. Make it very explicit."**

Every rule declares its data requirements explicitly. A rule that blocks IPs needs the source IP, nothing else. A rule that validates a request body needs the body, not the user's session history. A rule that analyses attack patterns needs the relevant logs, not the full traffic stream. **Each rule gets a minimal, explicit data grant.**

The benefits the voice memo named:

| Benefit | Why |
|---------|-----|
| **Testing** | A rule with explicit, minimal inputs is trivially testable |
| **Performance** | A rule that only touches what it needs is fast; no wasted data marshalling |
| **Understanding** | Explicit data requirements make it clear exactly what each rule does |
| **Security** | A rule cannot misuse data it was never given; blast radius contained |

This is the single-responsibility principle applied to rules. The voice memo: **"the rules should be single-responsibility, almost like a function. Instead of having functions in code, we just have rules."** Each rule is a small, single-purpose, explicitly-scoped unit. The engine composes them; each one does one thing.

This maps directly onto the per-rule IAM model. A rule's data grant is its privilege scope. The same least-privilege discipline that governs TUI API access governs rule data access. **A rule is a function with an IAM scope.**

## Version Control Per Rule

The voice memo specified: **every rule is version-controlled using RFD-style versioning** (major.minor.patch, e.g. 0.4.0, 0.14.0, 1.0.0). Each rule carries its own version. Rules can eventually live in a separate repo; for now they live alongside the engine.

This matters because rules change constantly. Version control per rule means:

- Every rule change is tracked
- A rule can be rolled back to a previous version independently
- The active rule-set is a manifest of rule versions
- A deployment is a set of rule versions, reproducible and auditable
- Rule changes have history, attribution, and review trails

The RFD (Request For Discussion) logic the voice memo referenced means rules are not just version-numbered but follow a discussion-and-decision process for significant changes. A new rule or a significant rule change goes through a lightweight RFD; the version number reflects the maturity (0.x for evolving, 1.0+ for stable).

This composes with the vault model: **rules are content; the rule repository can be a vault; rule versions are vault commits.** The version control, audit trail, and review process all come from the vault infrastructure we already have. A rule-set is a vault; deploying SG/Sentinel deploys a rule-set vault to the edge.

## The LLM Usage Pattern: Heavy In Development, Minimal In Production, Never Inline

A critical principle the voice memo stated with emphasis, and one with strong security justification: **LLMs are used heavily to build, test, threat-model, and architect rules, but in production they run minimally, asynchronously, and never inline.**

The pattern:

| Phase | LLM Usage |
|-------|-----------|
| **Rule development** | Heavy: LLMs help design rules, generate them, find edge cases |
| **Rule testing** | Heavy: LLMs generate test cases, adversarial inputs, validation |
| **Threat modelling** | Heavy: LLMs reason about what each rule should defend against |
| **Architecture** | Heavy: LLMs help design the rule structure and composition |
| **Production (inline)** | Never: no LLM ever runs in the inline request path |
| **Production (async)** | Minimal: LLMs run out-of-line for analysis that feeds back to fast rules |

The voice memo was unequivocal: **"in production there should be either no LLM or minimum LLM, and inline there should never be an LLM. All the work done by LLM should always be done out-of-line."**

The reasons are both security and performance:

**Security**: an inline LLM is an inline dependency on a complex, probabilistic system. That is an attack surface and a reliability risk in the request path. Keeping LLMs out-of-line means the request path is deterministic, fast, and auditable. The LLM's probabilistic judgement informs the rules; it does not make inline decisions.

**Performance**: an inline LLM call adds latency measured in hundreds of milliseconds to seconds. That is unacceptable in the request path. Out-of-line, the LLM has all the time it needs.

The model is: **LLMs do the slow, smart work of figuring out what the rules should be; the fast deterministic rules do the actual inline enforcement.** This is the "slow analysis, fast enforcement" pattern from the execution-model brief, applied to rule generation. The LLM is a rule author and analyst, not an inline decision-maker.

The voice memo also connected this to semantic knowledge graphs: **the out-of-line LLM work should produce semantic knowledge graphs, mapping things accordingly.** The analysis is not just "block this"; it builds structured knowledge about traffic, threats, and patterns that informs rule generation over time. This connects to the semantic-graph work in the MyFeeds and evidence-pack direction from earlier in the week.

## How The Rules Engine Composes With The Series

The rules engine is the heart that the other briefs surround:

| Brief | Relationship |
|-------|--------------|
| Principles brief | Established the why; named the candidates SG/Sentinel was chosen from |
| Execution-model brief | The layers the rules run across (1/2/3) |
| MVP brief | The first deliverable; its blocking is rules; its logging is rules |
| **This rules-engine brief** | **The architecture of how rules work, which the whole system is built around** |

Everything is rules: the MVP's Layer 1 blocking is deterministic rules; its logging is rules; its cleanup is rules. The execution model's layers are where rules of different types run. The principles' "no invalid request" is enforced by rules. **The rules engine is not one component among many; it is the thing SG/Sentinel is.**

## What This Asks For

Concrete next steps:

1. **Design the tiny core engine**: the minimal, high-privilege rule-execution machine.
2. **Define the rule schema**: how a rule declares its inputs, outputs, data requirements, layer, LLM needs.
3. **Build the per-rule least-privilege mechanism**: each rule gets only the data it declares.
4. **Establish RFD-style version control for rules**: versioning, history, the rule-set-as-vault model.
5. **Build the deterministic rule type first** (Layer 1): the fast, single-responsibility rules.
6. **Build the rule composition mechanism**: rules of rules, groups, handovers.
7. **Build the rule testing framework**: each rule tested in isolation with strong schemas.
8. **Establish the LLM-assisted rule development workflow**: LLMs author and test rules out-of-line.
9. **Build the out-of-line LLM analysis path** (Layer 3): analysis that feeds rules back, never inline.
10. **Define the semantic-knowledge-graph output** from the async LLM analysis.
11. **Document the update-risk gradient**: the review process for rule vs engine changes.

Estimated effort: 2-3 weeks for the core engine and the deterministic rule type with versioning and testing. The LLM-assisted development workflow and the async analysis path are follow-on, building on the MVP.

## What This Does Not Try To Be

Deliberate scope limits:

- **Not a fixed-engine WAF with rules as config.** The inversion is the point: rules are the substance, not configuration.
- **Not LLM-inline.** Never; the LLM is a rule author and async analyst only.
- **Not a finished rule library.** The MVP has a starter set; the rule library grows continuously.
- **Not a separate rules repo yet.** Rules live alongside the engine for now; separate repo later.
- **Not the full rule-type spectrum in v1.** Deterministic rules first; the LLM-driven types follow.

## Honest Risks

Three risks:

**Risk 1: The rules-are-everything model could make the engine too clever and the rules too fragmented.** If everything is a rule, simple things might require many rules. Mitigation: rule composition (rules of rules) keeps it manageable; good defaults; the engine handles common patterns so rules stay focused.

**Risk 2: Constant rule changes could introduce regressions.** Rules change daily; a bad rule change could break protection or block legitimate traffic. Mitigation: per-rule testing; the update-risk gradient (rules are low-risk because tested in isolation); observe-mode before enforce; version control with fast rollback.

**Risk 3: The per-rule least-privilege model could add overhead.** Explicitly scoping every rule's data could be tedious or slow. Mitigation: make the common case easy (sensible default scopes); the explicitness pays off in testing and security; measure the overhead and optimise the engine, not the rules.

## Open Questions

| Question | Notes |
|----------|-------|
| Rule schema format? | Probably declarative (YAML/JSON) for the contract, code for the logic |
| Rules-as-vault: when do rules move to their own repo/vault? | Alongside the engine for now; separate when the library grows |
| How are rules composed? | Rules of rules, groups, explicit handovers; the composition grammar needs defining |
| RFD process weight for rule changes? | Light for minor, heavier for new rules or significant changes |
| Default data scope for a rule? | Minimal; explicit grants required for more |
| How does the engine enforce per-rule data scopes? | The engine marshals only declared data to each rule |
| Semantic knowledge graph format for async analysis? | Connect to the evidence-pack semantic-graph work |
| Can rules be shared across SG/Sentinel deployments? | Yes; rules-as-vault makes this natural; a shared rule library |

## Relationship To Previous Briefs

| Date | Document | Relationship |
|---|---|---|
| 18 May | `v0.27.58__arch-brief__edge-security-and-logging-layer-principles.md` | Named the candidates; SG/Sentinel chosen here |
| 18 May | `v0.27.58__arch-brief__edge-layer-execution-model-layered-responders.md` | The layers the rules run across |
| 18 May | `v0.27.58__dev-brief__edge-layer-mvp-visibility-blocking-deployment.md` | The MVP whose blocking and logging are rules |
| 17 May | `v0.27.55__arch-brief__tui-api-extensions-iam-memfs-orientation.md` | The per-rule least-privilege mirrors the per-tool IAM model |
| 17 May | `v0.27.55__arch-brief__myfeeds-website-rebuild-three-primitives.md` | Rules-as-vault uses the same management-layer pattern |
| 17 May | `v0.27.55__strategy-brief__myfeeds-b2b-research-briefings-as-evidence-packs.md` | Semantic knowledge graphs connect to the evidence-pack work |
| 16 May | `v0.27.45__dev-brief__nova-and-agentcore-poc-fastapi.md` | Nova for the light-LLM async rules |
| 16 May | `v0.27.45__strategy-brief__appsec-mini-tools-on-top-of-vaults.md` | SG/Sentinel is an AppSec tool; rules-as-vault fits the pattern |
| 14 May | `v0.27.41__arch-brief__vaults-of-vaults-self-contained-mini-apps.md` | Rule-set as a vault; the manager pattern |
| 13 May | `v0.27.40__arch-brief__cli-first-agent-architecture.md` | The CLI-first discipline applies to rule management |

---

## Acceptance Criteria

| # | Criterion | Verification |
|---|-----------|-------------|
| 1 | The name SG/Sentinel is adopted across the series and code | Consistent naming |
| 2 | The tiny core engine executes rules and does nothing else | Engine is minimal; behaviour is in rules |
| 3 | Every behaviour (block, allow, log, cleanup) is expressed as a rule | No hardcoded behaviour in the engine |
| 4 | The rule schema (inputs, outputs, data needs, layer, LLM needs) is defined | Schema documented |
| 5 | Per-rule least privilege works (each rule gets only declared data) | Verified; rules cannot access undeclared data |
| 6 | Rules are version-controlled with RFD-style versioning | Each rule versioned; rollback works |
| 7 | Deterministic Layer 1 rules work | Fast, single-responsibility, no dependencies |
| 8 | Rule composition (rules of rules, groups) works | Composition verified |
| 9 | Each rule is testable in isolation | Test framework per rule |
| 10 | No LLM runs inline in production | Verified; LLM is dev/test/async only |
| 11 | Out-of-line LLM analysis feeds rules back | The slow-analysis-fast-enforcement loop works |
| 12 | The update-risk gradient is reflected in the review process | Rule changes vs engine changes treated differently |

---

This document is released under the Creative Commons Attribution 4.0 International licence (CC BY 4.0).
