@@ -272,15 +272,16 @@ describe("the status mirror hands a runAs:'user' cascade the person's own reques
272272 expect ( 'permissions' in write , 'the write carries no permission sets of its own' ) . toBe ( false ) ;
273273 }
274274
275+ /** The consumers first (what an author's automation sees), then the producer fact that explains it. */
275276 async function expectPersonInOrg ( seen : { write : any ; hook : any ; flow : any } , userId : string , org : string ) {
276- expectAttributedWrite ( seen . write , userId , org ) ;
277277 const expected = await requestEnvelope ( userId , org ) ;
278278 expect ( seen . hook . userId ) . toBe ( userId ) ;
279279 expect ( seen . hook . isSystem ) . toBe ( false ) ;
280280 expect ( envelopeOf ( seen . hook ) , "the runAs:'user' hook" ) . toEqual ( expected ) ;
281281 expect ( seen . flow . userId ) . toBe ( userId ) ;
282282 expect ( envelopeOf ( seen . flow ) , "the runAs:'user' record-change flow" ) . toEqual ( expected ) ;
283- return expected ;
283+ expectAttributedWrite ( seen . write , userId , org ) ;
284+ return seen ;
284285 }
285286
286287 it ( 'open, through the approval node: the submitter in the record organisation, and no role held only in another organisation' , async ( ) => {
@@ -289,38 +290,42 @@ describe("the status mirror hands a runAs:'user' cascade the person's own reques
289290 const requestId = await openNode ( 'd_open' , 'submitter' , [ 'approver' ] ) ;
290291 const [ request ] = await ql . find ( 'sys_approval_request' , { where : { id : requestId } , context : SYS } ) ;
291292 expect ( request . organization_id , 'fixture premise: the request is stamped with the record organisation' ) . toBe ( ORG_A ) ;
292- const expected = await expectPersonInOrg ( await cascade ( before ) , 'submitter' , ORG_A ) ;
293+ const { hook , flow } = await expectPersonInOrg ( await cascade ( before ) , 'submitter' , ORG_A ) ;
293294 // The person whose memberships differ: what A grants, never what B does.
294- expect ( expected . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
295- expect ( expected . org_user_ids ) . toEqual ( [ 'approver' , 'peer' , 'submitter' ] ) ;
295+ expect ( hook . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
296+ expect ( flow . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
297+ expect ( sorted ( hook . org_user_ids ) ) . toEqual ( [ 'approver' , 'peer' , 'submitter' ] ) ;
296298 } ) ;
297299
298300 it ( 'decide approve: the approver carries the grant they hold beyond the baseline, and their organisation peers' , async ( ) => {
299301 await seedDeal ( 'd_approve' ) ;
300302 const requestId = await openNode ( 'd_approve' , 'submitter' , [ 'approver' ] ) ;
301303 const before = mark ( ) ;
302304 await svc . decide ( requestId , { decision : 'approve' , actorId : 'approver' } as any , asPerson ( 'approver' ) ) ;
303- const expected = await expectPersonInOrg ( await cascade ( before ) , 'approver' , ORG_A ) ;
304- expect ( expected . permissions ) . toContain ( EXTRA_SET ) ;
305- expect ( expected . org_user_ids ) . toEqual ( [ 'approver' , 'peer' , 'submitter' ] ) ;
305+ const { hook, flow } = await expectPersonInOrg ( await cascade ( before ) , 'approver' , ORG_A ) ;
306+ // The grant beyond the baseline is the approver's, so the automation that runs as them holds it.
307+ expect ( hook . permissions ) . toContain ( EXTRA_SET ) ;
308+ expect ( flow . permissions ) . toContain ( EXTRA_SET ) ;
309+ expect ( sorted ( hook . org_user_ids ) ) . toEqual ( [ 'approver' , 'peer' , 'submitter' ] ) ;
306310 } ) ;
307311
308312 it ( 'decide reject: the approver, in the record organisation' , async ( ) => {
309313 await seedDeal ( 'd_reject' ) ;
310314 const requestId = await openNode ( 'd_reject' , 'submitter' , [ 'approver' ] ) ;
311315 const before = mark ( ) ;
312316 await svc . decide ( requestId , { decision : 'reject' , actorId : 'approver' } as any , asPerson ( 'approver' ) ) ;
313- const expected = await expectPersonInOrg ( await cascade ( before ) , 'approver' , ORG_A ) ;
314- expect ( expected . permissions ) . toContain ( EXTRA_SET ) ;
317+ const { hook } = await expectPersonInOrg ( await cascade ( before ) , 'approver' , ORG_A ) ;
318+ expect ( hook . permissions ) . toContain ( EXTRA_SET ) ;
315319 } ) ;
316320
317321 it ( 'recall: the submitter, in the record organisation' , async ( ) => {
318322 await seedDeal ( 'd_recall' ) ;
319323 const requestId = await openNode ( 'd_recall' , 'submitter' , [ 'approver' ] ) ;
320324 const before = mark ( ) ;
321325 await svc . recall ( requestId , { actorId : 'submitter' } as any , asPerson ( 'submitter' ) ) ;
322- const expected = await expectPersonInOrg ( await cascade ( before ) , 'submitter' , ORG_A ) ;
323- expect ( expected . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
326+ const { hook, flow } = await expectPersonInOrg ( await cascade ( before ) , 'submitter' , ORG_A ) ;
327+ expect ( hook . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
328+ expect ( flow . positions ) . not . toContain ( ROLE_ONLY_IN_B ) ;
324329 } ) ;
325330
326331 it ( 'send back for revision: the approver, in the record organisation' , async ( ) => {
@@ -357,9 +362,10 @@ describe("the status mirror hands a runAs:'user' cascade the person's own reques
357362 const requestId = await openNode ( 'd_xorg' , 'submitter' , [ 'xorg' ] ) ;
358363 const before = mark ( ) ;
359364 await svc . decide ( requestId , { decision : 'approve' , actorId : 'xorg' } as any , asPerson ( 'xorg' ) ) ;
360- const expected = await expectPersonInOrg ( await cascade ( before ) , 'xorg' , ORG_A ) ;
365+ const { hook , flow } = await expectPersonInOrg ( await cascade ( before ) , 'xorg' , ORG_A ) ;
361366 // The record organisation's members (and the approver), never their own organisation's.
362- expect ( expected . org_user_ids ) . toEqual ( [ 'approver' , 'peer' , 'submitter' , 'xorg' ] ) ;
367+ expect ( sorted ( hook . org_user_ids ) ) . toEqual ( [ 'approver' , 'peer' , 'submitter' , 'xorg' ] ) ;
368+ expect ( sorted ( flow . org_user_ids ) ) . toEqual ( [ 'approver' , 'peer' , 'submitter' , 'xorg' ] ) ;
363369 } ) ;
364370
365371 it ( "the organisation is the record's live one: a record re-parented while its request was pending" , async ( ) => {
0 commit comments