@@ -359,8 +359,48 @@ func TestBatchUpdateMetadata(t *testing.T) {
359359OrganizationID :orgID ,
360360})
361361
362- // Create context with system actor so authorization passes
363- ctx := dbauthz .AsSystemRestricted (context .Background ())
362+ // Create roles with workspace permissions
363+ userRoles := rbac .Roles ([]rbac.Role {
364+ {
365+ Identifier :rbac .RoleMember (),
366+ User : []rbac.Permission {
367+ {
368+ Negate :false ,
369+ ResourceType :rbac .ResourceWorkspace .Type ,
370+ Action :policy .WildcardSymbol ,
371+ },
372+ },
373+ ByOrgID :map [string ]rbac.OrgPermissions {
374+ orgID .String (): {
375+ Member : []rbac.Permission {
376+ {
377+ Negate :false ,
378+ ResourceType :rbac .ResourceWorkspace .Type ,
379+ Action :policy .WildcardSymbol ,
380+ },
381+ },
382+ },
383+ },
384+ },
385+ })
386+
387+ agentScope := rbac .WorkspaceAgentScope (rbac.WorkspaceAgentScopeParams {
388+ WorkspaceID :workspaceID ,
389+ OwnerID :ownerID ,
390+ TemplateID :templateID ,
391+ VersionID :uuid .New (),
392+ })
393+
394+ ctx := dbauthz .As (context .Background (), rbac.Subject {
395+ Type :rbac .SubjectTypeUser ,
396+ FriendlyName :"testuser" ,
397+ Email :"testuser@example.com" ,
398+ ID :ownerID .String (),
399+ Roles :userRoles ,
400+ Groups : []string {orgID .String ()},
401+ Scope :agentScope ,
402+ }.WithCachedASTValue ())
403+
364404resp ,err := api .BatchUpdateMetadata (ctx ,req )
365405require .NoError (t ,err )
366406require .NotNil (t ,resp )
@@ -377,6 +417,7 @@ func TestBatchUpdateMetadata(t *testing.T) {
377417pub = & fakePublisher {}
378418now = dbtime .Now ()
379419workspaceID = uuid .MustParse ("12345678-1234-1234-1234-123456789012" )
420+ templateID = uuid .MustParse ("aaaabbbb-cccc-dddd-eeee-ffffffff0000" )
380421ownerID = uuid .MustParse ("87654321-4321-4321-4321-210987654321" )
381422orgID = uuid .MustParse ("11111111-1111-1111-1111-111111111111" )
382423agentID = uuid .MustParse ("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" )
@@ -446,12 +487,53 @@ func TestBatchUpdateMetadata(t *testing.T) {
446487OrganizationID :uuid .Nil ,// Invalid: fails dbauthz fast path validation
447488})
448489
449- // Create context with system actor so authorization passes
450- ctx := dbauthz .AsSystemRestricted (context .Background ())
490+ // Create roles with workspace permissions
491+ userRoles := rbac .Roles ([]rbac.Role {
492+ {
493+ Identifier :rbac .RoleMember (),
494+ User : []rbac.Permission {
495+ {
496+ Negate :false ,
497+ ResourceType :rbac .ResourceWorkspace .Type ,
498+ Action :policy .WildcardSymbol ,
499+ },
500+ },
501+ ByOrgID :map [string ]rbac.OrgPermissions {
502+ orgID .String (): {
503+ Member : []rbac.Permission {
504+ {
505+ Negate :false ,
506+ ResourceType :rbac .ResourceWorkspace .Type ,
507+ Action :policy .WildcardSymbol ,
508+ },
509+ },
510+ },
511+ },
512+ },
513+ })
514+
515+ agentScope := rbac .WorkspaceAgentScope (rbac.WorkspaceAgentScopeParams {
516+ WorkspaceID :workspaceID ,
517+ OwnerID :ownerID ,
518+ TemplateID :templateID ,
519+ VersionID :uuid .New (),
520+ })
521+
522+ ctx := dbauthz .As (context .Background (), rbac.Subject {
523+ Type :rbac .SubjectTypeUser ,
524+ FriendlyName :"testuser" ,
525+ Email :"testuser@example.com" ,
526+ ID :ownerID .String (),
527+ Roles :userRoles ,
528+ Groups : []string {orgID .String ()},
529+ Scope :agentScope ,
530+ }.WithCachedASTValue ())
531+
451532resp ,err := api .BatchUpdateMetadata (ctx ,req )
452533require .NoError (t ,err )
453534require .NotNil (t ,resp )
454535})
536+
455537// Test RBAC slow path - no RBAC object in context
456538// This test verifies that when no RBAC object is present in context, the dbauthz layer
457539// falls back to the slow path and calls GetWorkspaceByAgentID.
@@ -464,6 +546,7 @@ func TestBatchUpdateMetadata(t *testing.T) {
464546pub = & fakePublisher {}
465547now = dbtime .Now ()
466548workspaceID = uuid .MustParse ("12345678-1234-1234-1234-123456789012" )
549+ templateID = uuid .MustParse ("aaaabbbb-cccc-dddd-eeee-ffffffff0000" )
467550ownerID = uuid .MustParse ("87654321-4321-4321-4321-210987654321" )
468551orgID = uuid .MustParse ("11111111-1111-1111-1111-111111111111" )
469552agentID = uuid .MustParse ("dddddddd-dddd-dddd-dddd-dddddddddddd" )
@@ -524,8 +607,48 @@ func TestBatchUpdateMetadata(t *testing.T) {
524607},
525608}
526609
527- // Create context with system actor so authorization passes
528- ctx := dbauthz .AsSystemRestricted (context .Background ())
610+ // Create roles with workspace permissions
611+ userRoles := rbac .Roles ([]rbac.Role {
612+ {
613+ Identifier :rbac .RoleMember (),
614+ User : []rbac.Permission {
615+ {
616+ Negate :false ,
617+ ResourceType :rbac .ResourceWorkspace .Type ,
618+ Action :policy .WildcardSymbol ,
619+ },
620+ },
621+ ByOrgID :map [string ]rbac.OrgPermissions {
622+ orgID .String (): {
623+ Member : []rbac.Permission {
624+ {
625+ Negate :false ,
626+ ResourceType :rbac .ResourceWorkspace .Type ,
627+ Action :policy .WildcardSymbol ,
628+ },
629+ },
630+ },
631+ },
632+ },
633+ })
634+
635+ agentScope := rbac .WorkspaceAgentScope (rbac.WorkspaceAgentScopeParams {
636+ WorkspaceID :workspaceID ,
637+ OwnerID :ownerID ,
638+ TemplateID :templateID ,
639+ VersionID :uuid .New (),
640+ })
641+
642+ ctx := dbauthz .As (context .Background (), rbac.Subject {
643+ Type :rbac .SubjectTypeUser ,
644+ FriendlyName :"testuser" ,
645+ Email :"testuser@example.com" ,
646+ ID :ownerID .String (),
647+ Roles :userRoles ,
648+ Groups : []string {orgID .String ()},
649+ Scope :agentScope ,
650+ }.WithCachedASTValue ())
651+
529652resp ,err := api .BatchUpdateMetadata (ctx ,req )
530653require .NoError (t ,err )
531654require .NotNil (t ,resp )