[DAP][Approvals] Allow monolith to handle pattern based approvals
<!--IssueSummary start--> <details> <summary> Everyone can contribute. [Help move this issue forward](https://handbook.gitlab.com/handbook/marketing/developer-relations/contributor-success/community-contributors-workflows/#contributor-links) while earning points, leveling up and collecting rewards. </summary> - [Label this issue](https://contributors.gitlab.com/manage-issue?action=label&projectId=278964&issueIid=598446) </details> <!--IssueSummary end--> ### Problem to solve As a Duo Workflows user, I want to approve tool calls using wildcard patterns (e.g. `git checkout *`), so I can approve a class of similar tool invocations at once instead of being prompted for each individual call. Currently, tool call approvals are exact-match only — each unique set of arguments requires a separate approval. This creates friction for repetitive workflows where the user trusts a tool with a range of inputs (e.g. approving all `git` commands or all file reads under a specific directory). ### Proposal Extend the existing tool call approval system to support glob pattern matching alongside exact approvals: - Add a `patterns` storage key to the `ToolCallApprovals` value object, stored in the existing JSONB column alongside `call_args` - Introduce an `approved?` method that checks both exact hash matches and glob pattern matches (via `File.fnmatch`) - For `run_command` tools, extract the command string from the JSON arguments so users can write intuitive patterns like `git checkout *` - Update the `UpdateToolCallApprovals` GraphQL mutation to accept an optional `pattern` argument as an alternative to `toolCallArgs` - Add a `toolCallApproved` query field on the workflow type so clients can check approval status - Register `tool_call_pattern_approval` as a new server capability in the workhorse/API capability negotiation, gated behind the same feature flag as `tool_call_approval` ### Further details - Patterns are validated to be non-empty strings of at most 256 characters - The mutation enforces that exactly one of `toolCallArgs` or `pattern` is provided - Pattern matching uses Ruby's `File.fnmatch`, which supports `*`, `?`, and `[a-z]` style globs - The existing row-level locking (`FOR UPDATE NOWAIT`) is preserved for safe concurrent updates ### Links / references
issue