@@ -776,11 +776,19 @@ describe('updateInterfacePermissions - permissions', () => {
776776 } ) ;
777777
778778 it ( 'should only update permissions that do not exist when no config provided' , async ( ) => {
779- // Mock that some permissions already exist
779+ // Mock that some permissions already exist (with SHARE/SHARE_PUBLIC as they would be post-#11283)
780780 mockGetRoleByName . mockResolvedValue ( {
781781 permissions : {
782- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
783- [ PermissionTypes . AGENTS ] : { [ Permissions . USE ] : true } ,
782+ [ PermissionTypes . PROMPTS ] : {
783+ [ Permissions . USE ] : false ,
784+ [ Permissions . SHARE ] : false ,
785+ [ Permissions . SHARE_PUBLIC ] : false ,
786+ } ,
787+ [ PermissionTypes . AGENTS ] : {
788+ [ Permissions . USE ] : true ,
789+ [ Permissions . SHARE ] : false ,
790+ [ Permissions . SHARE_PUBLIC ] : false ,
791+ } ,
784792 } ,
785793 } ) ;
786794
@@ -892,30 +900,38 @@ describe('updateInterfacePermissions - permissions', () => {
892900 SystemRoles . USER ,
893901 expectedPermissionsForUser ,
894902 expect . objectContaining ( {
895- permissions : {
896- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
897- [ PermissionTypes . AGENTS ] : { [ Permissions . USE ] : true } ,
898- } ,
903+ permissions : expect . objectContaining ( {
904+ [ PermissionTypes . PROMPTS ] : expect . objectContaining ( { [ Permissions . USE ] : false } ) ,
905+ [ PermissionTypes . AGENTS ] : expect . objectContaining ( { [ Permissions . USE ] : true } ) ,
906+ } ) ,
899907 } ) ,
900908 ) ;
901909 expect ( mockUpdateAccessPermissions ) . toHaveBeenCalledWith (
902910 SystemRoles . ADMIN ,
903911 expectedPermissionsForAdmin ,
904912 expect . objectContaining ( {
905- permissions : {
906- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
907- [ PermissionTypes . AGENTS ] : { [ Permissions . USE ] : true } ,
908- } ,
913+ permissions : expect . objectContaining ( {
914+ [ PermissionTypes . PROMPTS ] : expect . objectContaining ( { [ Permissions . USE ] : false } ) ,
915+ [ PermissionTypes . AGENTS ] : expect . objectContaining ( { [ Permissions . USE ] : true } ) ,
916+ } ) ,
909917 } ) ,
910918 ) ;
911919 } ) ;
912920
913921 it ( 'should override existing permissions when explicitly configured' , async ( ) => {
914- // Mock that some permissions already exist
922+ // Mock that some permissions already exist (with SHARE/SHARE_PUBLIC as they would be post-#11283)
915923 mockGetRoleByName . mockResolvedValue ( {
916924 permissions : {
917- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
918- [ PermissionTypes . AGENTS ] : { [ Permissions . USE ] : false } ,
925+ [ PermissionTypes . PROMPTS ] : {
926+ [ Permissions . USE ] : false ,
927+ [ Permissions . SHARE ] : false ,
928+ [ Permissions . SHARE_PUBLIC ] : false ,
929+ } ,
930+ [ PermissionTypes . AGENTS ] : {
931+ [ Permissions . USE ] : false ,
932+ [ Permissions . SHARE ] : false ,
933+ [ Permissions . SHARE_PUBLIC ] : false ,
934+ } ,
919935 [ PermissionTypes . BOOKMARKS ] : { [ Permissions . USE ] : false } ,
920936 } ,
921937 } ) ;
@@ -1340,8 +1356,13 @@ describe('updateInterfacePermissions - permissions', () => {
13401356
13411357 it ( 'should leave all existing permissions unchanged when nothing is configured' , async ( ) => {
13421358 // Mock existing permissions with values that differ from defaults
1359+ // SHARE/SHARE_PUBLIC included as they would be in a post-#11283 DB document
13431360 const existingUserPermissions = {
1344- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
1361+ [ PermissionTypes . PROMPTS ] : {
1362+ [ Permissions . USE ] : false ,
1363+ [ Permissions . SHARE ] : false ,
1364+ [ Permissions . SHARE_PUBLIC ] : false ,
1365+ } ,
13451366 [ PermissionTypes . BOOKMARKS ] : { [ Permissions . USE ] : false } ,
13461367 [ PermissionTypes . MEMORIES ] : { [ Permissions . USE ] : false } ,
13471368 [ PermissionTypes . PEOPLE_PICKER ] : {
@@ -1400,10 +1421,14 @@ describe('updateInterfacePermissions - permissions', () => {
14001421 } ) ;
14011422
14021423 it ( 'should only update explicitly configured permissions and leave others unchanged' , async ( ) => {
1403- // Mock existing permissions
1424+ // Mock existing permissions (with SHARE/SHARE_PUBLIC as they would be post-#11283)
14041425 mockGetRoleByName . mockResolvedValue ( {
14051426 permissions : {
1406- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : false } ,
1427+ [ PermissionTypes . PROMPTS ] : {
1428+ [ Permissions . USE ] : false ,
1429+ [ Permissions . SHARE ] : false ,
1430+ [ Permissions . SHARE_PUBLIC ] : false ,
1431+ } ,
14071432 [ PermissionTypes . BOOKMARKS ] : { [ Permissions . USE ] : false } ,
14081433 [ PermissionTypes . MEMORIES ] : { [ Permissions . USE ] : false } ,
14091434 [ PermissionTypes . PEOPLE_PICKER ] : {
@@ -1729,8 +1754,12 @@ describe('updateInterfacePermissions - permissions', () => {
17291754 [ Permissions . UPDATE ] : true ,
17301755 [ Permissions . OPT_OUT ] : true ,
17311756 } ,
1732- // Other existing permissions
1733- [ PermissionTypes . PROMPTS ] : { [ Permissions . USE ] : true } ,
1757+ // Other existing permissions (with SHARE/SHARE_PUBLIC as they would be post-#11283)
1758+ [ PermissionTypes . PROMPTS ] : {
1759+ [ Permissions . USE ] : true ,
1760+ [ Permissions . SHARE ] : false ,
1761+ [ Permissions . SHARE_PUBLIC ] : false ,
1762+ } ,
17341763 [ PermissionTypes . BOOKMARKS ] : { [ Permissions . USE ] : true } ,
17351764 } ,
17361765 } ) ;
@@ -2005,4 +2034,70 @@ describe('updateInterfacePermissions - permissions', () => {
20052034 expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] ) . not . toHaveProperty ( Permissions . SHARE ) ;
20062035 expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] ) . not . toHaveProperty ( Permissions . SHARE_PUBLIC ) ;
20072036 } ) ;
2037+
2038+ it ( 'should backfill SHARE/SHARE_PUBLIC when missing from an existing permission type (PR #11283 migration)' , async ( ) => {
2039+ // Simulates an existing deployment that has PROMPTS/AGENTS permissions from before PR #11283
2040+ // introduced SHARE/SHARE_PUBLIC. SHARED_GLOBAL existed previously; after the schema change
2041+ // the DB document has neither SHARE nor SHARE_PUBLIC set.
2042+ mockGetRoleByName . mockResolvedValue ( {
2043+ permissions : {
2044+ [ PermissionTypes . AGENTS ] : {
2045+ [ Permissions . USE ] : true ,
2046+ [ Permissions . CREATE ] : true ,
2047+ // SHARE and SHARE_PUBLIC intentionally absent — legacy pre-#11283 document
2048+ } ,
2049+ [ PermissionTypes . PROMPTS ] : {
2050+ [ Permissions . USE ] : true ,
2051+ [ Permissions . CREATE ] : true ,
2052+ // SHARE and SHARE_PUBLIC intentionally absent — legacy pre-#11283 document
2053+ } ,
2054+ [ PermissionTypes . MCP_SERVERS ] : {
2055+ [ Permissions . USE ] : true ,
2056+ [ Permissions . CREATE ] : true ,
2057+ [ Permissions . SHARE ] : false ,
2058+ // SHARE_PUBLIC intentionally absent — added later
2059+ } ,
2060+ } ,
2061+ } ) ;
2062+
2063+ // Boolean configs — these should NOT override the backfilled values
2064+ const config = {
2065+ interface : {
2066+ agents : true ,
2067+ prompts : true ,
2068+ } ,
2069+ } ;
2070+ const configDefaults = {
2071+ interface : { agents : true , prompts : true } ,
2072+ } as TConfigDefaults ;
2073+ const interfaceConfig = await loadDefaultInterface ( { config, configDefaults } ) ;
2074+ const appConfig = { config, interfaceConfig } as unknown as AppConfig ;
2075+
2076+ await updateInterfacePermissions ( {
2077+ appConfig,
2078+ getRoleByName : mockGetRoleByName ,
2079+ updateAccessPermissions : mockUpdateAccessPermissions ,
2080+ } ) ;
2081+
2082+ const userCall = mockUpdateAccessPermissions . mock . calls . find (
2083+ ( call ) => call [ 0 ] === SystemRoles . USER ,
2084+ ) ;
2085+
2086+ // AGENTS: SHARE and SHARE_PUBLIC should be backfilled with USER role defaults
2087+ expect ( userCall [ 1 ] [ PermissionTypes . AGENTS ] ) . toHaveProperty ( Permissions . SHARE ) ;
2088+ expect ( userCall [ 1 ] [ PermissionTypes . AGENTS ] ) . toHaveProperty ( Permissions . SHARE_PUBLIC ) ;
2089+ // USER role default for SHARE is false
2090+ expect ( userCall [ 1 ] [ PermissionTypes . AGENTS ] [ Permissions . SHARE ] ) . toBe ( false ) ;
2091+ expect ( userCall [ 1 ] [ PermissionTypes . AGENTS ] [ Permissions . SHARE_PUBLIC ] ) . toBe ( false ) ;
2092+
2093+ // PROMPTS: same backfill behaviour
2094+ expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] ) . toHaveProperty ( Permissions . SHARE ) ;
2095+ expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] ) . toHaveProperty ( Permissions . SHARE_PUBLIC ) ;
2096+ expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] [ Permissions . SHARE ] ) . toBe ( false ) ;
2097+ expect ( userCall [ 1 ] [ PermissionTypes . PROMPTS ] [ Permissions . SHARE_PUBLIC ] ) . toBe ( false ) ;
2098+
2099+ // MCP_SERVERS: SHARE already exists, only SHARE_PUBLIC should be backfilled
2100+ expect ( userCall [ 1 ] [ PermissionTypes . MCP_SERVERS ] ) . toHaveProperty ( Permissions . SHARE_PUBLIC ) ;
2101+ expect ( userCall [ 1 ] [ PermissionTypes . MCP_SERVERS ] ) . not . toHaveProperty ( Permissions . SHARE ) ;
2102+ } ) ;
20082103} ) ;
0 commit comments