# SG/Sentinel TUI Mockups: The Operator Surfaces As Acceptance Criteria

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

---

## What This Is

The TUI mockups document for SG/Sentinel, the companion to the architecture-and-data-flows brief. Where that brief maps how the system works, this one shows what the operator-facing surfaces look like, as ASCII-art mockups of the TUIs and CLIs. Together they are the acceptance criteria the dev team implements against.

The voice memo asked to "go to town" on this: a whole series of mockups covering the workflows, so we get a feel for what needs to be implemented. The workflows named: **rules management, deployment, what is deployed, what is happening right now, log visualisation, blocking visualisation, threat intelligence, browsing the stored S3 files, reviewing the deployed code, and the code architecture.** Built with Textual, per the TUI thread.

A principle runs through all of them, from the TUI API work: **every one of these UIs must be chatbot-friendly.** You can click and operate, but you can also just talk to it: ask what is happening, ask why something was blocked, ask to see a rule. The TUI API (parallel to the JS API) makes each surface programmatically addressable and chatbot-addressable. The voice memo: **every UI needs to be chatbot-friendly, so I can talk to it, not just click.**

These are starting-point mockups, not final designs (per the first-five-screens exploration framing). They make the workflows concrete enough to implement and react to.

## The Chatbot-Friendly Principle

Before the mockups, the principle that shapes them all. Each TUI has a chat affordance: a way to talk to the surface in natural language, backed by the TUI API. The chat can answer questions ("why was this IP blocked?"), drive actions ("disable rule 0042"), and explain state ("what is happening right now?").

This appears in the mockups as a chat pane or a chat command (`:chat` or a persistent input). The TUI API underneath makes the surface's state and actions available to the chatbot, so the conversation is grounded in the real, current state. **The TUI is the visual surface; the chat is the conversational surface; both are views of the same TUI API.**

## Mockup 1: What Is Deployed (Deployment Reality)

The at-a-glance view of what SG/Sentinel is running where.

```
┌─ SG/Sentinel: Deployment ──────────────────── 18 May 2026 14:32 ─┐
│                                                                    │
│ DISTRIBUTIONS                                                      │
│   prod-main         ●  d2x9k.cloudfront.net    Sentinel v0.27.58  │
│   prod-static       ●  d8h3p.cloudfront.net    Sentinel v0.27.58  │
│   staging           ●  d4f7q.cloudfront.net    Sentinel v0.27.58  │
│   dev-local         ◐  localhost:8443          Sentinel v0.27.58  │
│                                                                    │
│ LAYERS (prod-main)                                                 │
│   Layer 1 (CF Func)  ●  47 rules    last deploy 2h ago            │
│   Layer 2 (L@Edge)   ●  23 rules    last deploy 2h ago            │
│   Layer 3 (async)    ●  8 analysers running                       │
│                                                                    │
│ PHASE STATUS                                                       │
│   dev    ●  52 rules (incl 5 dangerous dev-only)                  │
│   main   ●  47 rules (QA passing)                                 │
│   prod   ●  47 rules (= main; deploy parity OK)                   │
│                                                                    │
│ LOGGING                                                            │
│   Destination   s3://sg-sentinel-logs/prod-main/                  │
│   Status        ●  delivering (last write 0.4s ago)              │
│   Rate          ~340 events/min                                   │
│                                                                    │
│ [r]efresh [d]eploy [t]eardown [c]ode [:]chat [q]uit                │
│ > chat: "is prod in sync with main?"                               │
└────────────────────────────────────────────────────────────────────┘
```

Shows: distributions, per-layer rule counts, phase status (with deploy-parity check), logging destination and health. The chat line at the bottom is the chatbot affordance.

## Mockup 2: What Is Happening Right Now (Live Traffic)

The real-time traffic view, the thing the project lead most wants.

```
┌─ SG/Sentinel: Live ──────────────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ LIVE EVENTS (newest first)                                          │
│ 14:32:11.3  ●  allow   GET /vault/john-cv     203.0.113.5   18ms    │
│ 14:32:10.9  ●  allow   GET /static/index.html 198.51.100.2  8ms     │
│ 14:32:10.2  ⚠  BLOCK   GET /etc/passwd        185.x.x.x     L1      │
│ 14:32:09.7  ⚠  BLOCK   GET /wp-login.php      91.x.x.x      L1      │
│ 14:32:09.1  ●  allow   GET /vault/demo-acct   203.0.113.5   21ms    │
│ 14:32:08.8  ◐  flag    GET /api/v1/unusual    77.x.x.x      L2      │
│ 14:32:08.2  ⚠  BLOCK   GET /.env              185.x.x.x     L1      │
│ 14:32:07.9  ●  allow   GET /static/style.css  198.51.100.2  6ms     │
│                                                                      │
│ THROUGHPUT (5min)                                                    │
│   Allow   ▆▇▆▅▇▆▅▆▇█▇▅▄▃▄▅▆▇▆▅  ~310/min                            │
│   Block   ▁▂▁▁▃▁▁▂▁▁▁▄▁▁▁▂▁▁▁▁  ~28/min                            │
│   Flag    ▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁  ~2/min                             │
│                                                                      │
│ TOP BLOCKED PATHS:  /etc/passwd (12)  /wp-login.php (9)  /.env (7)  │
│                                                                      │
│ [Space]pause [f]ilter [b]locks-only [:]chat [q]uit                  │
│ > chat: "why are we seeing so many /etc/passwd?"                     │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: live event stream (allow/block/flag, colour-coded), throughput sparklines, top blocked paths. The chat can explain patterns ("why so many /etc/passwd?").

## Mockup 3: Blocking Visualisation

A focused view on what is being blocked and why.

```
┌─ SG/Sentinel: Blocks ────────────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ BLOCKS (last hour: 1,847)                                           │
│ REASON                          COUNT   LAYER   RULE               │
│ ───────────────────────────────────────────────────────────────    │
│ Path never valid (/etc/passwd)    412    L1     0012               │
│ WordPress scan (static site)      388    L1     0018               │
│ Hidden file probe (/.env etc)     301    L1     0014               │
│ Banned region                     247    L1     0003               │
│ Malformed request                 198    L1     0007               │
│ Out-of-profile (app-coupled)      156    L2     0041               │
│ Anomaly score over threshold       98    L2     0055               │
│ Known scanner signature            47     L1     0021               │
│                                                                      │
│ BLOCK ACTIONS                                                        │
│   Dropped silently   1,402                                          │
│   Deflected (404)      298                                          │
│   Wild goose chase     147                                          │
│                                                                      │
│ [Enter]drill-into-rule [t]imeline [e]xport [:]chat [q]uit           │
│ > chat: "show me everything we blocked from 185.x.x.x"              │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: blocks grouped by reason, with the rule that fired and the layer. Block actions (dropped/deflected/wild-goose-chase). Drill into a rule, or chat to investigate an IP.

## Mockup 4: Log Visualisation And S3 Browsing

Viewing the logs and browsing the stored S3 files.

```
┌─ SG/Sentinel: Logs ──────────────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ S3: s3://sg-sentinel-logs/prod-main/                                │
│ ├─ 2026/05/18/                                                       │
│ │  ├─ 14/  events-1432.ndjson.gz   (2.3 MB, 18,402 events)         │
│ │  ├─ 13/  events-1300.ndjson.gz   (2.1 MB, 16,891 events)         │
│ │  └─ 12/  events-1200.ndjson.gz   (1.9 MB, 15,203 events)         │
│ └─ 2026/05/17/  (24 files)                                          │
│                                                                      │
│ SELECTED: events-1432.ndjson.gz                                     │
│   req-id        time      verdict  path           ip       layer   │
│   a1b2-7g3k     14:32:11  allow    /vault/john-cv 203...    -       │
│   a1b2-7g3l     14:32:10  block    /etc/passwd    185...    L1      │
│   a1b2-7g3m     14:32:10  block    /wp-login.php  91...     L1      │
│   ...                                                                │
│                                                                      │
│ TRACE req-id a1b2-7g3l:                                              │
│   L1 rule 0012 (path never valid) → BLOCK → logged → dropped        │
│                                                                      │
│ [Enter]open [/]search [trace]by-id [:]chat [q]uit                   │
│ > chat: "summarise the blocks in this file"                          │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: the S3 file tree (where logs land), a selected file's contents, and a trace of a specific request ID through the rules (the IDs-everywhere traceability). Chat can summarise.

## Mockup 5: Rules Management

The core rule-management surface, with schemas in and out.

```
┌─ SG/Sentinel: Rules ─────────────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ RULE GRAPH                          [tree view]                      │
│ ▼ security/                                                          │
│   ▼ easy-wins/  (pack, 18 rules)                                     │
│     ● 0012  path-never-valid       L1  det   ATT&CK:T1190  v1.2.0   │
│     ● 0014  hidden-file-probe      L1  det   ATT&CK:T1083  v1.1.0   │
│     ● 0018  wp-scan-static-site    L1  det   ATT&CK:T1595  v1.0.0   │
│   ▼ app-coupled/  (pack, 12 rules)                                   │
│     ● 0041  known-good-profile     L2  det   ATT&CK:T1190  v0.8.0   │
│     ◐ 0055  anomaly-score          L2  op    multi         v0.5.0   │
│   ▶ injection/  (pack, 24 rules, CRS-derived)                        │
│ ▼ logging/  (pack, 6 rules)                                          │
│   ● 0001  capture-all             L1  det   compliance:8.2  v2.0.0  │
│                                                                      │
│ SELECTED: 0012 path-never-valid                                     │
│   Schema in:   { method, path }                                     │
│   Schema out:  { verdict: allow|block, reason }                     │
│   Confidence:  deterministic (certain)                              │
│   Next rules:  → 0001 (log)                                         │
│   Standard:    OWASP A01; Attack: T1190                             │
│   Status:      ● enabled (prod, main, dev)                          │
│                                                                      │
│ [Enter]edit [n]ew [t]est [enable/disable] [:]chat [q]uit            │
│ > chat: "create a rule to block requests for .git directories"       │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: the fractal rule graph (packs within packs), each rule with its layer, determinism, ATT&CK mapping, and version. The selected rule shows its schema in, schema out, confidence, next rules, standard/attack mapping, and phase status. Chat can author rules (the agentic rule-writing).

## Mockup 6: Rule Detail And Testing

Drilling into a single rule to develop and test it.

```
┌─ SG/Sentinel: Rule 0055 anomaly-score ───────── 18 May 2026 14:32 ─┐
│                                                                      │
│ METADATA                                                             │
│   ID:          0055            Version:  v0.5.0                      │
│   Layer:       L2              Confidence: opinion (anomaly)         │
│   Standard:    OWASP A03       Attack:   multiple                    │
│   Data needs:  { headers, path, query, method }   (least-privilege) │
│                                                                      │
│ SCHEMA IN                          SCHEMA OUT                        │
│   { headers: {...},                { score: int,                     │
│     path: str,                       contributes: bool,              │
│     query: str,                      reason: str }                   │
│     method: str }                                                    │
│                                                                      │
│ LOGIC (Python; same code dev→prod)                                  │
│   def evaluate(req) -> Verdict:                                      │
│     score = 0                                                        │
│     if suspicious_user_agent(req): score += 2                        │
│     if unusual_path_depth(req):    score += 1                        │
│     ...                                                              │
│     return Verdict(score=score, ...)                                 │
│                                                                      │
│ TEST                                                                 │
│   ● 14 tests passing   ◐ 2 adversarial cases pending               │
│   Differential: [enable] vs [disable] on sample → run               │
│                                                                      │
│ [e]dit [r]un-tests [d]ifferential [history] [:]chat [q]uit          │
│ > chat: "what false positives could this rule cause?"                │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: full rule metadata, schema in/out, the actual Python logic (readable, same code dev-to-prod), test status (including adversarial cases), and the differential-test affordance (enable vs disable). Chat can reason about false positives.

## Mockup 7: Reviewing The Deployed Code

The voice memo specifically wanted to read the deployed code, since it should be simple.

```
┌─ SG/Sentinel: Deployed Code ─────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ DISTRIBUTION: prod-main    LAYER: 1 (CloudFront Function)            │
│                                                                      │
│ DEPLOYED BUNDLE (v0.27.58, 2h ago)                                  │
│   engine.js          142 lines   (tiny core; rule executor)         │
│   rules/             47 rules    (deterministic, embedded)          │
│   data/banned-ips    1,204 entries                                  │
│   data/banned-regions 18 entries                                    │
│                                                                      │
│ engine.js (the tiny core, read-only view)                           │
│   1  // SG/Sentinel Layer 1 core - executes rules, no I/O           │
│   2  function handler(event) {                                       │
│   3    const req = event.request;                                    │
│   4    const id = assignId(req);                                     │
│   5    for (const rule of ENTRY_RULES) {                            │
│   6      const verdict = rule(req);                                  │
│   7      log(id, rule.id, verdict);                                  │
│   8      if (verdict.block) return blockResponse(verdict);          │
│   9      if (verdict.next) queueNext(verdict.next);                 │
│  10    }                                                             │
│  11    return req;  // pass                                          │
│  12  }                                                               │
│                                                                      │
│ ✓ This is the exact code running in prod-main right now             │
│                                                                      │
│ [Enter]open-file [diff-vs-main] [verify-deployed] [:]chat [q]uit    │
│ > chat: "explain what this engine does line by line"                 │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: the deployed bundle contents, and the actual deployed code (the tiny core engine, readable because it is small). The "this is the exact code running in prod right now" confirmation matters: the operator can read precisely what is deployed. Chat can explain the code.

## Mockup 8: Threat Intelligence

The threat-intel view (from the research brief): the sources, the enrichment, what we know.

```
┌─ SG/Sentinel: Threat Intel ──────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ SOURCES (async, out-of-band)                                        │
│   AbuseIPDB     ●  connected   1,204 IPs enriched today             │
│   GreyNoise     ●  connected   scanner classification active        │
│   Spamhaus      ●  feed loaded 12,402 networks                      │
│   OTX (ATT&CK)  ●  connected   pulses mapped to techniques          │
│                                                                      │
│ IP: 185.x.x.x  (currently blocked)                                  │
│   AbuseIPDB     confidence 94%  (1,243 reports)                     │
│   GreyNoise     classified: scanner (mass-scanning, not targeted)   │
│   Our evidence  47 blocks in last hour; all out-of-profile          │
│   ATT&CK        T1595 (Active Scanning), T1190 (Exploit Public App) │
│   Verdict       blocked by rule 0012 + reputation context           │
│                                                                      │
│   ⚠ Note: residential-proxy risk; IP reputation is context not      │
│     verdict (our app-coupling is the primary signal)                │
│                                                                      │
│ [Enter]drill-IP [s]ources [e]vidence-graph [:]chat [q]uit           │
│ > chat: "what do you know about 185.x.x.x?"                          │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: the threat-intel sources (async), and for a specific IP, the enrichment from each source, our own evidence, the ATT&CK mapping, and the verdict, with the residential-proxy caveat noted (reputation is context, not verdict). The chat is literally the "what do you know about me?" feature.

## Mockup 9: Deployment (The CLI Flow)

The deployment lifecycle, shown as a TUI wrapping the CLI.

```
┌─ SG/Sentinel: Deploy ────────────────────────── 18 May 2026 14:32 ─┐
│                                                                      │
│ TARGET: prod-main (d2x9k.cloudfront.net)                            │
│ BUNDLE: v0.27.58 (main branch, QA passing)                          │
│                                                                      │
│ PRE-DEPLOY CHECKS                                                    │
│   ● Main = QA passing (deploy parity OK)                            │
│   ● No dangerous dev-only rules in bundle                          │
│   ● 47 rules, all tested                                            │
│   ● Bundle size: L1 1.2MB, L2 4.8MB                                 │
│                                                                      │
│ DEPLOY PLAN                                                          │
│   1. Build phase-aware bundle (prod rules only)                     │
│   2. Deploy Layer 1 (CloudFront Function)                           │
│   3. Deploy Layer 2 (Lambda@Edge)                                   │
│   4. Verify deployed = intended                                     │
│   5. Confirm logging to S3                                          │
│                                                                      │
│   [▸ Deploy]   [dry-run]   [diff vs current]                        │
│                                                                      │
│ RECENT DEPLOYS                                                       │
│   v0.27.58  2h ago    ● success   (current)                         │
│   v0.27.57  1d ago    ● success                                     │
│                                                                      │
│ [d]eploy [teardown] [rollback] [:]chat [q]uit                       │
│ > chat: "what changed between v0.27.57 and v0.27.58?"                │
└──────────────────────────────────────────────────────────────────────┘
```

Shows: the deploy target and bundle, pre-deploy checks (including deploy-parity and no-dangerous-rules), the deploy plan, and recent deploys with rollback. Chat can diff versions.

## What These Mockups Cover Together

| Mockup | Workflow | Voice Memo Named |
|--------|----------|------------------|
| 1. Deployment reality | What is deployed | Yes |
| 2. Live traffic | What is happening now | Yes |
| 3. Blocking | Blocking visualisation | Yes |
| 4. Logs + S3 | Log visualisation, browsing S3 files | Yes |
| 5. Rules management | Rules management with schemas | Yes |
| 6. Rule detail + test | Rules with schemas in/out | Yes |
| 7. Deployed code | Reviewing/seeing the code | Yes |
| 8. Threat intel | Threat intelligence sources | Yes |
| 9. Deploy | Deployment | Yes |

Every workflow the voice memo named is covered. Every mockup is chatbot-friendly (the chat line). Together with the architecture brief, these are the implementable acceptance criteria.

## What These Mockups Are And Are Not

- **They are starting points**, not final designs (the exploration framing from the first-five-screens brief).
- **They are acceptance criteria**: the dev team implements toward these, refining as they go.
- **They are chatbot-friendly throughout**: every surface talks, via the TUI API.
- **They are built with Textual** (the TUI thread framework choice).
- **They are not exhaustive**: more surfaces will emerge; these cover the named workflows.

## What This Asks For

1. **Implement these surfaces with Textual**, starting with the two first use cases (logs, blocks).
2. **Wire each to the TUI API** so it is chatbot-friendly and programmatically addressable.
3. **Prioritise: live traffic (2), blocks (3), logs+S3 (4), rules (5)** for the MVP.
4. **Make the deployed-code view (7) real** so the operator can read exactly what is deployed.
5. **Connect threat intel (8)** to the async sources from the research brief.
6. **Refine the mockups** based on use; promote the ones that earn it.

Estimated effort: 2-3 weeks for the MVP surfaces (live, blocks, logs, rules), building on the Textual TUI work and the TUI API.

## Honest Risks

**Risk 1: The mockups could be over-built before validated.** Mitigation: implement the MVP four first; refine from use.

**Risk 2: Chatbot-friendliness could be bolted on rather than designed in.** Mitigation: the TUI API is the foundation; the chat is a view of it, not an afterthought.

**Risk 3: The deployed-code view could expose sensitive detail.** Mitigation: read-only; dev/operator-only; the code is meant to be simple and readable, not secret.

## Relationship To Previous Briefs

| Date | Document | Relationship |
|---|---|---|
| 18 May | `v0.27.58__arch-brief__sg-sentinel-architecture-and-data-flows.md` | The architecture companion to these mockups |
| 18 May | `v0.27.58__arch-brief__sg-sentinel-rule-architecture-strategy.md` | The rule graph the rules surfaces show |
| 18 May | `v0.27.58__research-brief__sentinel-learning-from-standards-and-services.md` | The threat-intel sources mockup 8 shows |
| 17 May | `v0.27.55__dev-brief__sg-edge-tui-first-five-screens.md` | The exploration framing and screen patterns |
| 17 May | `v0.27.55__arch-brief__tui-api-structured-surface-for-text-uis.md` | The TUI API that makes these chatbot-friendly |
| 17 May | `v0.27.55__dev-brief__sg-edge-rich-tui-experiments.md` | The Textual framework choice |

---

## Acceptance Criteria

| # | Criterion | Verification |
|---|-----------|-------------|
| 1 | All nine workflow surfaces are implementable from these mockups | Dev team can build |
| 2 | Every surface is chatbot-friendly via the TUI API | Chat works on each |
| 3 | The live-traffic surface shows real-time events | Hot data visible |
| 4 | The blocking surface shows blocks by reason and rule | Investigable |
| 5 | The logs surface browses S3 and traces by request ID | Traceability works |
| 6 | The rules surface shows the fractal graph with metadata | Rule graph navigable |
| 7 | The rule-detail surface shows schemas in/out and logic | Rules developable |
| 8 | The deployed-code surface shows exactly what is running | Operator can read it |
| 9 | The threat-intel surface shows sources and enrichment | "What do you know about me?" works |
| 10 | The deploy surface handles the lifecycle with parity checks | Deploy/rollback works |
| 11 | Built with Textual | Framework consistent |
| 12 | These + the architecture brief are implementable acceptance criteria | MVP buildable |

---

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