@@ -111,14 +111,17 @@ describe('#20552 — a served definition withholds the hook secret', () => {
111111 expect ( startOf ( spies . registerFlow . mock . calls [ 0 ] ! [ 1 ] ) . config . secret ) . toBe ( SECRET ) ;
112112 } ) ;
113113
114- it ( 'POST /:name/clone — the answer withholds it; the clone carries the whole definition ' , async ( ) => {
115- const { dispatcher, flows } = makeDispatcher ( ) ;
114+ it ( 'POST /:name/clone — a credential-holding source is refused, and the refusal carries no credential ' , async ( ) => {
115+ const { dispatcher, flows, spies } = makeDispatcher ( ) ;
116116 const result = await dispatcher . handleAutomation ( '/inbound_hook/clone' , 'POST' , { name : 'inbound_hook_copy' , label : 'Copy' } , AUTHOR ) ;
117- expect ( result . response ?. status ) . toBe ( 200 ) ;
117+ // #20790 C1: a copy would share the source's secret, so the clone door
118+ // refuses it (the refusal itself is pinned in
119+ // `automation-flow-clone-credential.test.ts`).
120+ expect ( result . response ?. status ) . toBe ( 409 ) ;
121+ expect ( result . response ?. body ?. error ?. code ) . toBe ( 'RESOURCE_CONFLICT' ) ;
118122 expect ( JSON . stringify ( result . response ?. body ) ) . not . toContain ( SECRET ) ;
119- // ADR-0126 §7.1's whole-definition copy is unchanged: the registered
120- // clone still verifies its hook with the source's secret.
121- expect ( startOf ( flows . get ( 'inbound_hook_copy' ) ) ! . config . secret ) . toBe ( SECRET ) ;
123+ expect ( flows . has ( 'inbound_hook_copy' ) ) . toBe ( false ) ;
124+ expect ( spies . registerFlow ) . not . toHaveBeenCalled ( ) ;
122125 } ) ;
123126} ) ;
124127
0 commit comments