@@ -913,7 +913,7 @@ describe("API", () => {
913913 expect ( res . status ) . toBe ( 403 ) ;
914914 } ) ;
915915
916- it ( "filter[taskIdentifier]=task_a,task_b + JWT read:tasks:task_a → passes (array match )" , async ( ) => {
916+ it ( "filter[taskIdentifier]=task_a,task_b + JWT read:tasks:task_a → 403 (requires every task )" , async ( ) => {
917917 const server = getTestServer ( ) ;
918918 const seed = await seedTestEnvironment ( server . prisma ) ;
919919 const jwt = await generateJWT ( {
@@ -928,11 +928,9 @@ describe("API", () => {
928928 const res = await get ( "?filter%5BtaskIdentifier%5D=task_a%2Ctask_b" , {
929929 Authorization : `Bearer ${ jwt } ` ,
930930 } ) ;
931- // Resource array is [{type:"runs"}, {type:"tasks",id:"task_a"}, {type:"tasks",id:"task_b"}].
932- // The scope read:tasks:task_a matches the second element → access granted.
933- // Handler may 500 (ClickHouse unreachable in tests) but auth passed.
934- expect ( res . status ) . not . toBe ( 401 ) ;
935- expect ( res . status ) . not . toBe ( 403 ) ;
931+ // A task-scoped JWT must authorize every requested task so including an
932+ // unauthorized task in a multi-task filter cannot expose its runs.
933+ expect ( res . status ) . toBe ( 403 ) ;
936934 } ) ;
937935
938936 it ( "filter[taskIdentifier]=task_a + JWT read:tasks:task_z → 403 (no array match)" , async ( ) => {
@@ -2473,13 +2471,14 @@ describe("API", () => {
24732471 expect ( res . status ) . not . toBe ( 403 ) ;
24742472 } ) ;
24752473
2476- it ( "read:tasks (type-only) on no-filter list: 403 (filter is sessions, not tasks) " , async ( ) => {
2477- // No filter → resource is `{ type: "sessions" }` only. read:tasks
2478- // doesn't match the sessions type, so 403 — explicit narrowing .
2474+ it ( "read:tasks (type-only) on no-filter list: auth passes " , async ( ) => {
2475+ // Preserve the legacy behavior where a type-level task scope grants
2476+ // access to an unfiltered list while task ID scopes require a filter .
24792477 const seed = await seedTestEnvironment ( getTestServer ( ) . prisma ) ;
24802478 const jwt = await mintJwt ( seed . apiKey , seed . environment . id , [ "read:tasks" ] ) ;
24812479 const res = await fetchWithJwt ( jwt ) ;
2482- expect ( res . status ) . toBe ( 403 ) ;
2480+ expect ( res . status ) . not . toBe ( 401 ) ;
2481+ expect ( res . status ) . not . toBe ( 403 ) ;
24832482 } ) ;
24842483
24852484 it ( "write:tasks:foo (wrong action) on filter=foo: 403" , async ( ) => {
0 commit comments