Skip to content

The console sends a per-rule system_prompt that no page can read or edit #16

Description

@Indervertrag2

What happened

/prompt is the console's only interactive surface for the VLM system prompt. Its
heading reads "Edit the system prompt for the Vision Language Model"
(src/app/prompt/page.tsx:148-150). Saving patches the VLM_SYSTEM_PROMPT env var
on the vss-rtvi-vlm Deployment and restarts it: src/app/api/prompt/route.ts:157
calls reconcilePrompt, and src/lib/reconcile/prompt.ts:24-25 does exactly
patchDeploymentEnv + restartDeployment. POST /api/profiles/{name} applies a
profile's vlmPrompt through the same env var
(src/app/api/profiles/[name]/route.ts:99-100).

Independently of that, every realtime alert rule the console creates carries its
own system prompt, read from the realtime-alert-rules ConfigMap and put on the
wire per rule:

src/lib/helpers/ingestion.ts:198    systemPrompt: doc?.system_prompt,
src/lib/helpers/alert-bridge.ts:82  if (input.systemPrompt !== undefined)
                                      body.system_prompt = input.systemPrompt;

That value is shown nowhere in the console and cannot be changed from it. A
repository-wide search for system_prompt outside tests returns four hits: the
type declaration, the read above, the wire helper above, and the field name in a
PRESERVE array. None of them is a writer.

So the page that says it edits the VLM system prompt edits a different value from
the one the console transmits, and the transmitted one has no surface at all.
What happened:
/prompt is the console's only interactive surface for the VLM system prompt. Its
heading reads "Edit the system prompt for the Vision Language Model"
(src/app/prompt/page.tsx:148-150). Saving patches the VLM_SYSTEM_PROMPT env var
on the vss-rtvi-vlm Deployment and restarts it: src/app/api/prompt/route.ts:157
calls reconcilePrompt, and src/lib/reconcile/prompt.ts:24-25 does exactly
patchDeploymentEnv + restartDeployment. POST /api/profiles/{name} applies a
profile's vlmPrompt through the same env var
(src/app/api/profiles/[name]/route.ts:99-100).

Independently of that, every realtime alert rule the console creates carries its
own system prompt, read from the realtime-alert-rules ConfigMap and put on the
wire per rule:

src/lib/helpers/ingestion.ts:198    systemPrompt: doc?.system_prompt,
src/lib/helpers/alert-bridge.ts:82  if (input.systemPrompt !== undefined)
                                      body.system_prompt = input.systemPrompt;

That value is shown nowhere in the console and cannot be changed from it. A
repository-wide search for system_prompt outside tests returns four hits: the
type declaration, the read above, the wire helper above, and the field name in a
PRESERVE array. None of them is a writer.

So the page that says it edits the VLM system prompt edits a different value from
the one the console transmits, and the transmitted one has no surface at all.

What you expected instead

Either of these would be consistent:

  • /prompt reads and writes the value the console actually sends, re-registering
    the affected rules the way PATCH /api/tuning/sampling already does
    (src/app/api/tuning/sampling/route.ts:145-176), or
  • /prompt names which of the two it edits, and shows the per-rule system_prompt
    read-only beside it.

The console already proves it knows the field exists: system_prompt is in the
PRESERVE array at src/app/api/tuning/sampling/route.ts:145-150, so that a
sampling change does not drop it while deleting and re-posting each rule. It is
carried through, never shown.

The same holds for enable_reasoning, read at src/lib/helpers/ingestion.ts:202,
forwarded at src/lib/helpers/alert-bridge.ts:86, preserved on line 147, and
surfaced nowhere. It decides whether incident summaries carry the model's
reasoning text, which is a visible product of this UI.

Steps to reproduce

Entirely from the repository, no deployment required.

  1. Follow the save path from the only prompt surface:
    src/app/prompt/page.tsx:148-150 -> src/app/api/prompt/route.ts:157 ->
    src/lib/reconcile/prompt.ts:24-25, which patches promptKey and restarts.
    promptKey is VLM_SYSTEM_PROMPT (src/lib/cluster-refs.ts:358).

  2. Follow the rule-creation path: src/lib/helpers/ingestion.ts:198 takes
    system_prompt from the rules ConfigMap and passes it to addRealtimeRule,
    which writes it into the request body at src/lib/helpers/alert-bridge.ts:82.

  3. grep -rn "system_prompt" src/ --exclude=".test."
    Four hits, no writer.

  4. grep -rn "system_prompt|rules.json" docs/
    No hits. The field is undocumented.

On a running console the two values can be compared directly: read the text on
/prompt, then read system_prompt on GET /api/v1/realtime after
recreating a rule via PUT /api/cameras/ with {"ingestion":{"enabled":false}}
then true, which is the path that rebuilds it
(src/app/api/cameras/[id]/route.ts:157).

This report makes no claim about which value the VLM ends up using; that is
decided outside this repository. The defect stands either way: the console can
neither show nor edit a value it sends itself.

How it is running

In-cluster Kubernetes pod (namespace console)

Console version

4688890

VSS profile and storage

alerts profile, Helm chart vss-3.2.1. Object storage is ARTESCA 4.3.0-rc.1.

Diagnostics

Not applicable: both code paths are in this repository and no cluster state is
needed to see them.

Before submitting

  • This is not a security vulnerability. (Those go through the Security tab — see SECURITY.md.)
  • I have redacted credentials, tokens and internal hostnames.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions