@@ -77,17 +77,16 @@ func TestNativeAgentOwnershipLifecycle(t *testing.T) {
7777 require .NoError (t , err )
7878 require .Equal (t , runtimev0 .InitStatus_READY , initialized .GetStatus ().GetState (), initialized .GetStatus ().GetMessage ())
7979 startNativeWorkload (t , ctx , a )
80- owner , err := runners .InspectProcess (a .owner .PID )
81- if err != nil {
82- t .Fatal (err )
83- }
84- // The current PID must still be the original authenticated manager child.
85- // SignalProcess rechecks that identity at delivery; never select a new birth.
86- require .Equal (t , a .owner , owner , "agent owner birth changed before signaling" )
87- t .Logf ("owner pre-signal identity equals original: %+v" , a .owner )
88- if err := runners .SignalProcess (ctx , a .owner , syscall .SIGKILL ); err != nil {
89- t .Fatal (err )
90- }
80+ // A stale birth must be refused before SIGKILL delivery. If this guard
81+ // delivered to the live PID, the exact owner and workload checks would fail.
82+ stale := a .owner
83+ stale .StartID ++
84+ require .ErrorContains (t , signalNativeOwner (ctx , stale ), "owner identity changed" )
85+ assertNativeOwnership (t , ctx , a , true )
86+ assertNativeOwnership (t , ctx , b , true )
87+ t .Log ("stale owner refused with original agent and uvicorn births still alive" )
88+ require .NoError (t , signalNativeOwner (ctx , a .owner ))
89+ t .Logf ("signaled owner only after full identity matched original: %+v" , a .owner )
9190 waitNativeCondition (t , func () bool {
9291 ownership , err := a .group .InspectOwnership (ctx )
9392 return err == nil && ownership .Authenticated && ! ownership .OwnerAlive
@@ -103,7 +102,7 @@ func TestNativeAgentOwnershipLifecycle(t *testing.T) {
103102 t .Fatalf ("preview: %v" , err )
104103 }
105104 expected , err := runners .ParseProcessGroupRecoveryExpectation (preview )
106- if err != nil || expected .Namespace != "authenticated-v2" || expected .PGID != a .group .PGID () || expected .Owner .PID != owner .PID || expected .Owner .BootID != owner .BootID || expected .Owner .StartID != owner .StartID {
105+ if err != nil || expected .Namespace != "authenticated-v2" || expected .PGID != a .group .PGID () || expected .Owner .PID != a . owner .PID || expected .Owner .BootID != a . owner .BootID || expected .Owner .StartID != a . owner .StartID {
107106 t .Fatalf ("actual agent did not write the expected v2 registration: %+v, %v" , expected , err )
108107 }
109108 t .Logf ("orphan preview: %s" , preview )
@@ -266,6 +265,19 @@ func startNativeWorkload(t *testing.T, ctx context.Context, service *ownedNative
266265 })
267266}
268267
268+ // signalNativeOwner is only the fixture's admission guard. Core owns delivery
269+ // and rechecks the current full identity at the kernel-bound signal seam.
270+ func signalNativeOwner (ctx context.Context , original runners.ProcessIdentity ) error {
271+ current , err := runners .InspectProcess (original .PID )
272+ if err != nil {
273+ return err
274+ }
275+ if current != original {
276+ return fmt .Errorf ("owner identity changed: original=%+v current=%+v" , original , current )
277+ }
278+ return runners .SignalProcess (ctx , current , syscall .SIGKILL )
279+ }
280+
269281func assertNativeOwnership (t * testing.T , ctx context.Context , service * ownedNativeService , ownerAlive bool ) {
270282 t .Helper ()
271283 ownership , err := service .group .InspectOwnership (ctx )
0 commit comments