Skip to content

bug: POST /api/operator-queue/{id}/respond accepts any string as an approval decision — no layer checks response ∈ options #2376

Description

@webmixgamer

Summary

OperatorResponse.response is a bare str; the router, the DB write and the agent write-back pass it through verbatim, and no layer checks that an approval item's recorded decision is one of the options the agent offered. #2370 shipped response: "approved" against options: ["Approve", "Deny"] for five months without a single 4xx — a server-side membership check would have turned the first tap into a named 422.

Context

The operator queue is the approval channel for irreversible agent actions (#1402 poison-park, ent#329 respond→resume, the TARGET_ARCHITECTURE v2 human-gate). Four producers exist today (desktop store, /m, the Workspace asks panel, the MCP tool) and the next one — a channel button, an ops agent — can re-ship the class unless the sink refuses. Defence in depth at the boundary (Product Quality Bar #6: a named validation error, never a silently broken state). Surfaced by the #2370 plan review.

Acceptance Criteria

  • For an item with type == 'approval' and real options (a non-empty list that is not the size-cap marker _OPTIONS_DROPPED_MARKER), a response not in options is rejected with a named 422 (e.g. response_not_an_offered_option) that lists the offered options; exact string match (options are agent-authored)
  • Question items, alert items, approval items without usable options, and acknowledged are unaffected
  • The check lives in ONE place reached by both POST /api/operator-queue/{id}/respond and the Workspace asks answer path (src/backend/client_portal/asks/service.py) — a shared validator at the service/db chokepoint, not a copy per router
  • MCP respond_to_operator_queue surfaces the 422 as a structured error (no silent success)
  • Tests: accept / reject / exempt cases on both entry points, including the marker-list case

Technical Notes

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions