@@ -206,10 +206,115 @@ describe("gateway authorization kernel", () => {
206206 } ) ;
207207 expect ( result ) . toEqual ( {
208208 allowed : true ,
209- security : { principalId : "principal-1" , domain : { id : "domain-1" } } ,
209+ security : {
210+ principalId : "principal-1" ,
211+ principalKind : "human" ,
212+ domain : { id : "domain-1" } ,
213+ method : "sessions.get" ,
214+ permission : "session.read" ,
215+ resources : [ resource ] ,
216+ } ,
217+ } ) ;
218+ } ) ;
219+
220+ it ( "snapshots plugin action and resources before awaiting the provider" , async ( ) => {
221+ const mutableResource = { namespace : "core" , type : "session" , id : "session-original" } ;
222+ const policy = {
223+ kind : "resource" as const ,
224+ permission : "session.read" ,
225+ resolveResources : ( ) => [ mutableResource ] ,
226+ } ;
227+ let resolveDecision : ( ( ) => void ) | undefined ;
228+ const authorize = vi . fn (
229+ ( ) =>
230+ new Promise < {
231+ allowed : true ;
232+ principalId : string ;
233+ domain : { id : string } ;
234+ } > ( ( resolve ) => {
235+ resolveDecision = ( ) =>
236+ resolve ( { allowed : true , principalId : "principal-1" , domain : { id : "domain-1" } } ) ;
237+ } ) ,
238+ ) ;
239+ const pending = authorizeGatewayAccess ( {
240+ runtime : { mode : "isolated" , authorize } ,
241+ policy,
242+ principal,
243+ method : "sessions.get" ,
244+ params : { } ,
245+ getConfig : ( ) => config ,
246+ } ) ;
247+ await vi . waitFor ( ( ) => expect ( authorize ) . toHaveBeenCalledOnce ( ) ) ;
248+
249+ mutableResource . id = "session-forged" ;
250+ policy . permission = "session.write" ;
251+ resolveDecision ?.( ) ;
252+
253+ await expect ( pending ) . resolves . toEqual ( {
254+ allowed : true ,
255+ security : expect . objectContaining ( {
256+ permission : "session.read" ,
257+ resources : [ { namespace : "core" , type : "session" , id : "session-original" } ] ,
258+ } ) ,
210259 } ) ;
211260 } ) ;
212261
262+ it ( "snapshots the server delegation reference before awaiting the provider" , async ( ) => {
263+ const mutableDelegation = { id : "delegation-1" , assignmentId : "assignment-1" } ;
264+ let resolveDecision : ( ( ) => void ) | undefined ;
265+ const authorize = vi . fn (
266+ ( ) =>
267+ new Promise < {
268+ allowed : true ;
269+ principalId : string ;
270+ domain : { id : string } ;
271+ delegation : { id : string ; assignmentId : string ; sponsorPrincipalId : string } ;
272+ } > ( ( resolve ) => {
273+ resolveDecision = ( ) =>
274+ resolve ( {
275+ allowed : true ,
276+ principalId : "principal-agent" ,
277+ domain : { id : "domain-1" } ,
278+ delegation : {
279+ id : "delegation-1" ,
280+ assignmentId : "assignment-1" ,
281+ sponsorPrincipalId : "principal-owner" ,
282+ } ,
283+ } ) ;
284+ } ) ,
285+ ) ;
286+ const pending = authorizeGatewayAccess ( {
287+ runtime : { mode : "isolated" , authorize } ,
288+ policy : resourcePolicy ( ( ) => [ resource ] ) ,
289+ principal : { issuer : "core" , subject : "agent:main" , kind : "service" } ,
290+ delegation : mutableDelegation ,
291+ method : "sessions.get" ,
292+ params : { } ,
293+ getConfig : ( ) => config ,
294+ } ) ;
295+ await vi . waitFor ( ( ) => expect ( authorize ) . toHaveBeenCalledOnce ( ) ) ;
296+
297+ mutableDelegation . id = "injected-delegation" ;
298+ mutableDelegation . assignmentId = "injected-assignment" ;
299+ resolveDecision ?.( ) ;
300+
301+ await expect ( pending ) . resolves . toEqual ( {
302+ allowed : true ,
303+ security : expect . objectContaining ( {
304+ delegation : {
305+ id : "delegation-1" ,
306+ assignmentId : "assignment-1" ,
307+ sponsorPrincipalId : "principal-owner" ,
308+ } ,
309+ } ) ,
310+ } ) ;
311+ expect ( authorize ) . toHaveBeenCalledWith (
312+ expect . objectContaining ( {
313+ delegation : { id : "delegation-1" , assignmentId : "assignment-1" } ,
314+ } ) ,
315+ ) ;
316+ } ) ;
317+
213318 it . each ( [
214319 { principalId : "" , domain : { id : "domain-1" } } ,
215320 { principalId : "principal-1" , domain : { id : " " } } ,
0 commit comments