Skip to content

Commit c236601

Browse files
committed
feat(webapp): let an environment JWT read a queue, as it already reads its metrics
The dashboard agent asks for a queue's live row — paused, depth, limit — through the environment JWT it exchanges for. The metrics route has accepted that JWT all along; the retrieve route answered 401, so the agent saw no queue at all.
1 parent 711b79e commit c236601

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

apps/webapp/app/routes/api.v1.queues.$queueParam.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export const loader = createLoaderApiRoute(
1414
queueParam: z.string().transform((val) => val.replace(/%2F/g, "/")),
1515
}),
1616
searchParams: SearchParamsSchema,
17+
// An environment JWT may read a queue, the way it already reads that queue's metrics.
18+
// Same data class — name, depth, limit, paused — and the `queues` scope still gates it.
19+
allowJWT: true,
1720
findResource: async () => 1, // This is a dummy function, we don't need to find a resource
1821
authorization: {
1922
action: "read",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { readFileSync } from "node:fs";
2+
import { describe, expect, it } from "vitest";
3+
4+
/**
5+
* The agent reads a queue's live row — paused, depth, limit — through the environment JWT it
6+
* exchanges its delegated token for. Metrics already answer that JWT; without the same on the
7+
* retrieve route the agent got a 401, which reaches the model as absent data and had it
8+
* telling users a queue of thousands of runs did not exist.
9+
*/
10+
const ROUTE = "apps/webapp/app/routes/api.v1.queues.$queueParam.ts";
11+
const METRICS = "apps/webapp/app/routes/api.v1.queues.$queueParam.metrics.ts";
12+
13+
describe("queue retrieve accepts an environment JWT", () => {
14+
const source = readFileSync(ROUTE, "utf8");
15+
16+
it("allows the JWT, like its own metrics route does", () => {
17+
expect(source).toContain("allowJWT: true");
18+
expect(readFileSync(METRICS, "utf8")).toContain("allowJWT: true");
19+
});
20+
21+
it("keeps the queues scope as the gate", () => {
22+
// Widening who may ask must not widen what they may read.
23+
expect(source).toContain('resource: () => ({ type: "queues" })');
24+
expect(source).toContain('action: "read"');
25+
});
26+
});

0 commit comments

Comments
 (0)