Problem
#1211 added the store (/api/v1/guardrail-credentials) and #1244 made the gateway build every
stored row at startup. Both landed without a way to reach them from a browser: the only
interface today is curl.
The guardrails screen (/tools/guardrails) currently offers a guardrails_url field for the
old sidecar and the organization mandate card that names a profile. There is no way to
create the profile a mandate names, so the two halves do not meet.
What to build
Change the current guardrails screen. Add an operator-only card above the mandate card, with a
dialog that asks in the order an operator actually decides:
- What do you want checked? A dropdown of operations, for example prompt injection.
- Which guardrail? A second dropdown, disabled until the first is answered, listing the
guardrails that do that job.
- Its own fields. The chosen guardrail's
create_parameters and validate_parameters,
rendered typed, with credentials masked.
On submit the definition is stored, and the card lists what is in the database.
Supported actions: create, list, edit, delete, enable/disable, and test against a sample input.
The taxonomy is any-guardrail's, not ours
No category list, ordering, or copy is written down in this repository.
- Which operations exist is the union of
categories over the catalog entries.
- Which guardrails do one is
categories membership, not primary_category.
AnyGuardrail.group_by("category") is upstream's own grouping and its docstring states that
for a set-valued dimension "a guardrail appears under every value it carries".
primary_category exists to place a guardrail exactly once in grouped docs navigation, which
is not what a picker does. Using it would hide Alinia, Patronus and watsonx Guardian from
prompt injection although all three detect it, and four of the nine operations would never
appear at all.
- Ordering follows upstream:
group_by returns its keys sorted.
- The label is the existing mechanical helper
parameterLabel
(prompt_injection becomes Prompt injection). Formatting, not authored copy.
One gap worth noting: GuardrailCategory carries a one-line docstring per member, but Python
drops member docstrings at import, so the gateway cannot read them and no help line is shown
under the first dropdown. A follow-up asks any-guardrail to publish runtime-readable category
descriptions.
Scope
Frontend only. BuiltInGuardrailSpec already carries categories, and web/src/client/schema.ts
is already regenerated on feat-eager-guardrail-runner, so there is no backend change, no
OpenAPI or Postman regeneration, and no migration.
Out of scope: the reencrypt endpoint (key rotation lives on Settings beside the provider one),
feeding these names into the mandate card's profile picker (follow-up), and tenant scoping in
hosted mode (#818).
Success criteria
- An operator can define, edit, test, disable and remove a guardrail without leaving the browser.
- A stored credential is never prefilled and never echoed back, and an edit that touches another
field does not delete it.
- Adding a category upstream needs no change here.
- The three dashboard test suites pass.
Builds on #1211 and #1244. Supersedes #1114, whose draft PR #1137 targeted the superseded
#1116/#1120 stack.
Problem
#1211 added the store (
/api/v1/guardrail-credentials) and #1244 made the gateway build everystored row at startup. Both landed without a way to reach them from a browser: the only
interface today is
curl.The guardrails screen (
/tools/guardrails) currently offers aguardrails_urlfield for theold sidecar and the organization mandate card that names a
profile. There is no way tocreate the profile a mandate names, so the two halves do not meet.
What to build
Change the current guardrails screen. Add an operator-only card above the mandate card, with a
dialog that asks in the order an operator actually decides:
guardrails that do that job.
create_parametersandvalidate_parameters,rendered typed, with credentials masked.
On submit the definition is stored, and the card lists what is in the database.
Supported actions: create, list, edit, delete, enable/disable, and test against a sample input.
The taxonomy is any-guardrail's, not ours
No category list, ordering, or copy is written down in this repository.
categoriesover the catalog entries.categoriesmembership, notprimary_category.AnyGuardrail.group_by("category")is upstream's own grouping and its docstring states thatfor a set-valued dimension "a guardrail appears under every value it carries".
primary_categoryexists to place a guardrail exactly once in grouped docs navigation, whichis not what a picker does. Using it would hide Alinia, Patronus and watsonx Guardian from
prompt injection although all three detect it, and four of the nine operations would never
appear at all.
group_byreturns its keys sorted.parameterLabel(
prompt_injectionbecomesPrompt injection). Formatting, not authored copy.One gap worth noting:
GuardrailCategorycarries a one-line docstring per member, but Pythondrops member docstrings at import, so the gateway cannot read them and no help line is shown
under the first dropdown. A follow-up asks any-guardrail to publish runtime-readable category
descriptions.
Scope
Frontend only.
BuiltInGuardrailSpecalready carriescategories, andweb/src/client/schema.tsis already regenerated on
feat-eager-guardrail-runner, so there is no backend change, noOpenAPI or Postman regeneration, and no migration.
Out of scope: the
reencryptendpoint (key rotation lives on Settings beside the provider one),feeding these names into the mandate card's profile picker (follow-up), and tenant scoping in
hosted mode (#818).
Success criteria
field does not delete it.
Builds on #1211 and #1244. Supersedes #1114, whose draft PR #1137 targeted the superseded
#1116/#1120 stack.