Two questions almost every network architect we talk to asks within the first 20 minutes:
The honest answer to both is yes. The Regnor™ Topology page now ships a typed query language, a Claude-powered natural-language layer on top of it, and a Time Machine that reconstructs your network at any point in the past. All three were designed around a single safety contract — the LLM only proposes a query string; the authoritative parser is the only thing that ever executes. Your topology data never leaves your perimeter. Your model never sees a row.
This article walks through how it works and why we built it this way.
Most “natural language to data” features in this category do one of two things:
We rejected both. The Topology page ships a real typed DSL with real expressive power, and uses Claude only to translate your English into a candidate DSL string — which we then re-parse through the same authoritative parser as if you’d typed the DSL by hand.
If the model hallucinates, the parser rejects. If the model proposes something the DSL can’t express, you get a clean refusal, not a fuzzy guess. The model is never on the execution path.
The DSL is the foundation. Seven fields, tight grammar, no foot-guns.
Fields: vendor, model, os_version, device_type, site, last_seen, degree.
Operators: : is the only equality operator. (= is a parse error — typo-class confusion eliminated.) The comparison operators < > <= >= are valid only on the two ordered fields, last_seen and degree. Boolean composition is AND OR NOT with parentheses.
Durations are first-class. 7d, 2h, 30m. The lexer emits Duration tokens before numbers, so 7d is one token. A typo like 7y is a deliberate parse error — no silent unit coercion to seconds, no quiet zero result.
Examples that work today:
vendor:cisco AND last_seen<7d
(vendor:arista OR vendor:juniper) AND device_type:router
device_type:firewall AND NOT site:"London"
degree>10
After parse, a semantic check enforces DSL_LIMITS: raw query length ≤ 512 characters, ≤ 32 predicates, parse-tree depth ≤ 16. No expression bombs.
This is the part that matters for security-conscious buyers.
The parser never builds SQL. A separate compiler walks the validated AST and emits parameterized SQL where $1 is always the dispatcher-trusted org ID. NOT is pushed to the leaves via De Morgan so that SQL NOT(...) is never emitted — because NOT(NULL) = NULL in three-valued logic, which would silently drop NULL rows and create false-negative results in PCI/FedRAMP segmentation queries. We caught that class of bug at design time and structurally eliminated it.
Execution is bounded. Every DSL query runs in a transaction with SET LOCAL statement_timeout = 5000, an explicit WHERE organization_id = $1, and a 5000-row cap. A timeout returns a structured DSL_TOO_COMPLEX error, not a 500. Error messages are data-independent — byte-identical across orgs — so the error channel cannot leak whether a row exists in some other tenant.
The DSL is free. No spend gate. It carries a 120/min/org abuse limiter, that’s it.
The LLM proposes a candidate query string. The authoritative parser is the only thing that ever executes. There is no direct path from the model to the database.
POST /api/topology/query/nl accepts English. It is gated, before the controller, by four checks:
topology:query:nl permission (Viewer role is excluded — read access alone doesn’t grant query access).If any check fails, no model call ever happens.
If they all pass, we call Claude — specifically claude-haiku-4-5-20251001 at temperature: 0. Haiku, not Opus, because the answer-shape is bounded (a DSL string, max 512 chars) and we don’t burn the org’s premium model budget on it. Temperature zero because we want the same English to deterministically translate to the same DSL.
The grammar section of the prompt is generated at runtime from the DSL’s exported field set. A bidirectional contract test asserts that the prompt’s field list equals DSL_FIELDS so the two layers can’t drift. When we add a new field to the DSL, the prompt updates automatically and the test catches any divergence in CI.
A forced tool call means the model isn’t asked for prose — it’s asked for a DSL string in a structured field. Extraction is exhaustively defensive: own-property reads only, prototype-pollution-inert, never throws.
The translator only produces a candidate string. It never executes.
The controller takes Claude’s raw output and hands it verbatim back through the same authoritative parseDsl you’d hit if you typed it yourself. There is no trusted-AST shortcut. There is zero new SQL surface attached to the NL path.
Four concrete outcomes:
Four NL-translation outcomes. The model is never on the execution path; the parser decides everything.
A success returns a paraphrase rendered from the same re-parsed string. That fixed a real bug we caught in elicitation (66-5b): editing the DSL after translation would leave the English description stale. The paraphrase is now derived deterministically from the parsed AST, so what you read always matches what runs.
A red-team battery (8/8 tests) pins injection, cross-org-via-prompt, cost-bomb, and RBAC-separation against the real parser — not against a mock.
Every query path — typed DSL executor, NL re-parse, time-machine, overlays, analytics, unlinked-devices count — binds organization_id = $1 from the dispatcher-trusted principal in code, with Postgres row-level security as defense-in-depth. The org is never sourced from a request body, a prompt, or a model output. JWT-swap and cross-org adversarial tests are pinned across all four surfaces.
What this means for your security review: when you ask “does your NL feature ever let the LLM see customer data?”, the answer is no, structurally. The model receives your prompt, a grammar definition, and the available field names. It does not receive a row from your database. The query it proposes is re-parsed by the same parser that has been running against typed DSL since day one.
Same device positions, different active links. The scrubber rewinds the topology — and an amber caveat surfaces honestly when the past can’t be fully reconstructed.
Different problem, same engineering discipline.
A timeline scrubber at the bottom of the Topology canvas reconstructs the link topology at any historical point in time. Two modes:
The non-obvious bit: there’s no snapshot table, no event-sourcing replay log. Point-in-time is reconstructed purely from temporal columns on topology_links. The historical link predicate is exactly:
tl.organization_id = $1
AND tl.discovered_at <= $at
AND (tl.last_seen >= $at OR tl.last_seen IS NULL)
AND (tl.deleted_at IS NULL OR tl.deleted_at > $at)
A link is drawn at time T only if it was discovered by T, was still being observed at or after T (or has no last_seen at all — e.g. a manually asserted link), and had not been deleted as of T.
Historical nodes are edge-derived — on the time-travel path, only devices referenced by a surviving link get drawn. This makes “a device created after T appears in the past” structurally impossible. We don’t filter it out in the frontend; we never query it to begin with.
Deliberate invariant: when you scrub back to last Tuesday, the links change underneath your hand-pinned device positions, but the positions stay fixed. Your mental map of the network stays stable while the topology changes around it. That’s how an operator actually wants to think about history — “what was talking to what last Tuesday at 3 PM, on the same map I look at every day?”
Scrubbing through history while live WebSocket updates are still streaming in is a race-condition factory. We close the family with a monotonic epoch guard. Every async canvas mutation re-checks a monotonic tmEpochRef at apply time:
The Time Machine substrate cannot represent history for deleted devices. The device foreign key uses ON DELETE CASCADE, which hard-erases the links along with the device. Empirically: 114 device_deleted events in production, zero soft-deleted links.
Rather than silently render confidently-wrong history, the page shows a non-dismissable incompleteness caveat when this condition could apply. A compliance reviewer must never be allowed to trust an incomplete past as complete. We picked the harder UX over the comforting lie.
Trade-offs we made explicitly:
This is what we mean by “honest UI.” We’d rather ship less than ship a feature that’s misleading at the edges.
Three concrete workflows we’ve watched customers run in beta:
Incident investigation. Scrub to the moment the alert fired. See exactly which links were live, which devices were participating. Switch to since-then-diff mode and see what changed between then and now. No “what did the topology look like during the outage” Slack threads.
Compliance segmentation queries. Type “firewalls in any site except London that were last seen in the last 24 hours” into the NL bar. The DSL device_type:firewall AND NOT site:"London" AND last_seen<24h runs. Export the matched IDs for your auditor.
Drift triage. Open the Topology page on a NOC wall. Layer the drift overlay. Ask in English: “show me devices with drift that talk to SW1.” Get a highlighted answer on the canvas. No second tool.
We’re not promising the NL layer can express every question. The DSL is Phase A — no set operations, no aggregates, no free-text, no wildcards, no regex, no relational (“connected to”) predicates. When you ask something it can’t express, you get an empty-DSL refusal, not a wrong answer. That’s the design.
We’re not promising the Time Machine reconstructs deleted devices. The product tells you when it can’t, in a banner you can’t dismiss.
We’re not promising the NL feature lives at the same SLA as the typed DSL. NL is rate-limited per user, gated by RBAC, gated by AI spend cap, and degrades to typed DSL the moment any of those checks fails. Plain text search is always available regardless.
If you’re on Regnor™ Cloud beta:
vendor:cisco AND last_seen<7d) or switch to NL mode and type English.If you’re not on Regnor™ Cloud yet, start the beta.
The next iterations on the Topology query path (already in backlog):
connected_to:SW1) and saved DSL queries with version pinning.The point of the substrate we shipped first is that all of these layer on without re-litigating the safety contract. The parser is the only thing that executes. The org binding is from the dispatcher, not the request. The Time Machine reconstructs honestly or tells you it can’t. Every new feature inherits those guarantees by default.
Regnor™, Valdis™, and Tavrin™ are trademarks of AutomateNetOps (registration pending). The capabilities described in this article shipped as of 2026-05-24.
Tags: audit, dsl, honest-ui, llm-safety, natural-language, network-query, parser, regnor, sacred-positions, time-machine, topology, zero-trust
Categories: Network Automation, Security
Updated:
Three accreted pains retired: storage amplification, bolt-on attachments, and WAN re-pull. The Regnor™ unified document system is one fabric — content-addres...
How Regnor™ Lab Designer turns a slice of real production into a runnable lab — drag-canvas, lossless YAML round-trip, Clone/Branch/Match from prod, and a pe...