Repository navigation
Commit e2948f1
authored
feat(webapp): query boundary pinned end-to-end and a capped query retry (#4549)
## What & why
The agent's query tool is read-only, but that was true by three separate
facts and only one of them had a test. This proves the boundary holds by
contract rather than by prompt, and stops a broken query from burning a
whole agent turn.
Two small guards, the rest is tests.
[TRI-11165](https://linear.app/triggerdotdev/issue/TRI-11165).
## Stack
Stacked on **#4548** (watch-mode keepalive). Merge that first.
## What's inside
- **A route-level read-only test**
(`apps/webapp/test/queryRouteReadOnly.test.ts`) that drives
`api.v1.query` with a real signed environment JWT: a multi-statement
write and a mutating statement are both refused before anything reaches
ClickHouse, and a plain read passes so the seam stays live.
- **`readonly=1` made non-overridable** in `queryService.server.ts` —
caller `clickhouseSettings` were spread after the defaults and could
clear it.
- **A per-turn query-retry cap** in the agent's `run_query` tool
(`internal-packages/dashboard-agent/src/tool-api.ts`): three consecutive
failures returns a terminal "stop and answer with what you have".
## Key decisions
- **The read-only guarantee is grammar-level, not filtered.** TRQL has
no write statements — they don't parse — ClickHouse runs with
`readonly=1`, and the org/project/env scoping is injected server-side
from the credential. The request body can't widen scope or turn a read
into a write.
- **The deny test runs through the route, not the parser.** A
parser-only test would stay green if a refactor routed agent SQL around
the compiler; driving the real route with a signed JWT pins the boundary
end-to-end, and the deliberate positive read keeps the assertion honest.
- **The retry cap lives per turn, not in the prompt.** A failed query
hands the model the database error to fix, and usually it does — but the
only other limit was the turn's 10 steps, so one query the model
couldn't fix could eat the whole turn and leave the user with no answer.
The tool set is built per turn, so the counter caps consecutive
failures; a success resets it. The retry instruction rides the error
text, so the prompt prefix is unchanged.
## Testing
- `queryRouteReadOnly.test.ts` — write statements → 400, ClickHouse
never called; a read passes.
- `tool-query-retry-cap.test.ts` — terminal at the third consecutive
failure, counter resets on a success.
- The load-bearing guards were control-broken first (readonly override
re-enabled; cap removed) and the tests went red.1 parent 550b717 commit e2948f1
41 files changed
Lines changed: 5293 additions & 64 deletions
File tree
- .server-changes
- apps/webapp
- app
- components/dashboard-agent
- routes
- services
- test
- docs
- internal-packages
- dashboard-agent-db
- drizzle
- meta
- src
- dashboard-agent/src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
Lines changed: 5 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | | - | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | | - | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
30 | | - | |
31 | | - | |
32 | | - | |
| 31 | + | |
33 | 32 | | |
34 | 33 | | |
35 | 34 | | |
| |||
Lines changed: 27 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
102 | 103 | | |
103 | 104 | | |
104 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
105 | 109 | | |
106 | 110 | | |
107 | 111 | | |
| |||
128 | 132 | | |
129 | 133 | | |
130 | 134 | | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
131 | 147 | | |
132 | 148 | | |
133 | 149 | | |
| |||
185 | 201 | | |
186 | 202 | | |
187 | 203 | | |
188 | | - | |
189 | | - | |
190 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
191 | 210 | | |
192 | 211 | | |
193 | 212 | | |
| |||
252 | 271 | | |
253 | 272 | | |
254 | 273 | | |
| 274 | + | |
| 275 | + | |
255 | 276 | | |
256 | 277 | | |
257 | 278 | | |
| |||
264 | 285 | | |
265 | 286 | | |
266 | 287 | | |
267 | | - | |
| 288 | + | |
268 | 289 | | |
269 | 290 | | |
270 | 291 | | |
| |||
414 | 435 | | |
415 | 436 | | |
416 | 437 | | |
417 | | - | |
| 438 | + | |
418 | 439 | | |
419 | | - | |
| 440 | + | |
420 | 441 | | |
421 | 442 | | |
422 | 443 | | |
| |||
Lines changed: 41 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| 20 | + | |
19 | 21 | | |
20 | 22 | | |
21 | 23 | | |
| |||
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| 29 | + | |
27 | 30 | | |
28 | 31 | | |
29 | 32 | | |
| |||
43 | 46 | | |
44 | 47 | | |
45 | 48 | | |
| 49 | + | |
| 50 | + | |
46 | 51 | | |
47 | 52 | | |
48 | 53 | | |
49 | 54 | | |
50 | 55 | | |
51 | | - | |
| 56 | + | |
52 | 57 | | |
53 | 58 | | |
54 | 59 | | |
| |||
57 | 62 | | |
58 | 63 | | |
59 | 64 | | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
79 | 100 | | |
80 | 101 | | |
81 | 102 | | |
| |||
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| |||
114 | 115 | | |
115 | 116 | | |
116 | 117 | | |
| 118 | + | |
| 119 | + | |
117 | 120 | | |
118 | 121 | | |
119 | 122 | | |
| |||
260 | 263 | | |
261 | 264 | | |
262 | 265 | | |
| 266 | + | |
263 | 267 | | |
264 | 268 | | |
265 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
266 | 276 | | |
267 | 277 | | |
268 | 278 | | |
269 | 279 | | |
270 | 280 | | |
| 281 | + | |
271 | 282 | | |
272 | 283 | | |
273 | 284 | | |
| |||
309 | 320 | | |
310 | 321 | | |
311 | 322 | | |
| 323 | + | |
312 | 324 | | |
313 | 325 | | |
314 | 326 | | |
| |||
634 | 646 | | |
635 | 647 | | |
636 | 648 | | |
| 649 | + | |
637 | 650 | | |
638 | 651 | | |
639 | 652 | | |
| |||
Lines changed: 39 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
3 | 10 | | |
4 | 11 | | |
5 | 12 | | |
| |||
42 | 49 | | |
43 | 50 | | |
44 | 51 | | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
45 | 83 | | |
46 | 84 | | |
47 | 85 | | |
| |||
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
30 | 52 | | |
31 | 53 | | |
32 | 54 | | |
| |||
0 commit comments