Skip to content
Arif Dewi
Engineering Lead · Staff Full Stack / AI Engineer
Hiring me
Project · LLM safety & guardrails

Nexus Sentinel: a prompt firewall for any LLM

A self-hosted prompt firewall. One endpoint takes a prompt plus a policy and returns an allow, redact or block verdict with the evidence behind it. It judges text; it never generates it.

Open source · live demo on AWS·2026

Role and scopeSolo project: design, implementation, infrastructure and tests.

Context

Built to work through, end to end, how a prompt firewall should make decisions, under the constraints of a real service rather than a notebook: cost caps, rate limits, an audit trail, and a test suite that runs offline.

Detecting one bad prompt is the easy part. The design questions are what happens when the signals disagree, when a detector is down, or when the text has been disguised to slip past a filter, and how every verdict can be explained afterwards.

Scale

Interface
One endpoint, POST /v1/verify · 3 verdicts: allow, redact, block
Decision core
100% branch coverage · a pure function, no I/O
Throttling
20 req/s, burst 40 at API Gateway, then layered DynamoDB caps on billable calls
Dashboard
Lighthouse 100 × 4
Status
Open source · live demo on AWS

Architecture

POST /v1/verifysanitizestrip hidden · fold homoglyphsGuardrailsApplyGuardrailinjectionpre-screen ↳ haikuaggregatepure decision coreallowredactblock+ matches · scores · replayable audit

What I decided and built

  • ›Made Amazon Bedrock Guardrails the primary primitive, called directly through ApplyGuardrail, rather than asking the main model to police its own input. A model judging a prompt that may be attacking it is the component under attack; a dedicated guardrail is a separate, configurable check whose verdict does not depend on the prompt behaving. Sentinel never generates text; it only judges it.
  • ›Ran a separate Claude Haiku injection screener in parallel with the guardrail, using forced tool use so it returns structured indicators (instruction_override, system_prompt_extraction and others) instead of a single yes/no flag. A binary flag cannot be explained or tuned; named indicators can.
  • ›Normalized adversarial input before judging it: zero-width, bidi and Unicode-tag characters are stripped and homoglyphs are folded to ASCII, so both screeners see the real text. Obfuscation raises a signal and escalates but never blocks on its own, because legitimate Unicode (emoji joiners, combining marks) exists.
  • ›Kept the decision core a pure function: same inputs, same verdict, no I/O, no clock, no randomness. Each evidence source contributes block, redact or allow, and the strongest wins, so a prompt only has to fail one check to be stopped.
  • ›Chose the failure modes on purpose: fail closed when the guardrail errors (the request is rejected with a 503, because the primary signal is missing) and fail open when the injection screener errors (it degrades to skipped, so a flaky secondary check cannot take the firewall down).
  • ›Added cross-policy replay: any past request can be re-run under a different policy, answering "what would yesterday's prompt have done under today's policy?" before a policy change ships.
  • ›Built it as ports and adapters: the core depends on interfaces, never on the AWS SDK, and one switch swaps the whole adapter set between deterministic fakes and AWS. The full test suite and the demo run offline against the fakes; the AWS deployment runs the same core.
  • ›Bounded cost by design: throttling at API Gateway before any compute runs, layered DynamoDB caps on billable Bedrock calls, and a Budgets alarm. Lambda, API Gateway, CloudFront and DynamoDB, all defined in AWS CDK.

Evals and safety

The decision core has 100% branch coverage, and because it is a pure function every verdict is reproducible from its inputs. The suite runs offline against deterministic fakes, so it runs in CI on every change without an AWS account or a model bill.

Every verdict carries its evidence (matched categories, confidence scores and a redacted preview) and is written to an audit log that replay reads from. Structured logs never record raw prompts or keys.

The limits are named, not hidden. The offline fake mode uses pattern matching and cannot read intent, so a plainly worded request for illicit instructions gets through it. On AWS that class is handled by the Guardrails content filters and denied topics, which is a policy change rather than new code.

Outcome

  • ◆A working prompt firewall, open source with a live demo on AWS: one call returns an explainable allow, redact or block verdict and an audit record that can be replayed under a new policy.
  • ◆100% branch coverage on the decision core, and Lighthouse 100 × 4 on the dashboard.