What you're describing is "determinism" - this is the situation where two instances of your program can independently arrive at the same outcome, consistently, given the same input.
Determinism will not solve your problem here, because you do not have the same input.
The copy of your game running on the player's computer (the client) knows what move button they pressed at time 15:01.000. The copy running on the server does not find out about that action until one packet latency later - maybe 15:01.033, a full frame later.
From the client's perspective, you dodged the bullet just in time. From the server's perspective, you were a frame too late and the bullet hit you. Those are both correct simulation results for the input they were given. So even if your simulation rules are perfectly deterministic, you can get divergence: give different input, and you will get different results.
The simplest way to solve this is to decide by fiat that one of these versions of events will be honoured as the authoritative truth, and the other will be regarded as a temporary mirage, that quickly gets corrected to match this truth. In a client-server game, we'll usually choose the server to be this authority (because it can make it more difficult for players to cheat), and we call it an "authoritative server" model.
Here, the client's simulation result is considered to be a "prediction" - visualizing for the player what the results of their action should probably be, while we wait for confirmation from the server. The server independently simulates the results of the actions as it receives player input, and sends updates describing the outcomes.
When a client receives an update from the server that differs from its version of events, it applies a correction: blending (or in some cases, snapping) its local state to match the server's.
You can sometimes work around this to a degree with some time travel: when the server learns about some new player input, it estimates the time that input was sent, and rewinds the game simulation to that moment, applies the input, then re-simulates forward to find out what happened. This maintains one "consensus timeline" that more closely matches each player's view of the sequence of events in the game - especially relating to their own actions. But it can still run into surprises, where an action by a remote player that the local client doesn't know about yet changes the outcome of an event they've already predicted and displayed - so you still need to correct to the authoritative version of events in this case.
For your specific situations:
The client can perform the pathfinding query, then choose the first waypoint on the path and send that to the server so that it and all connected clients can animate the entity moving to that point. Keep sending the next waypoint each time you reach the previous one. You may need to re-path periodically if you learn about a new obstacle partway through pathing.
OnTriggerEnter with a bullet can trigger an animation (eg. a flinch) and sound effect so that the player gets immediate visceral feedback about the collision - but it should not be responsible for damaging or killing the entity on the client.
Instead, the server should be responsible for adjudicating whether a lethal hit occurred. When it does, it can send an "Entity killed" message to all connected clients, who can respond by transitioning that entity into its death state. The animation we started playing locally can help disguise the delay between the hit and the confirmation of the kill.
If no confirmation arrives, the entity can shrug off the illusory hit ("it just grazed me!") and continue unharmed. You may need to add a little extra showmanship though when killing an entity with a bullet that missed in your local simulation. Some extra particle effects can help sell the cause of death so it doesn't look like the entity just spontaneously croaked.