Practical tips for validating raw transactions I have a protocol that creates a raw signed transaction that is then broadcast to the network. The transaction aims to send X BTC to a single address Z. The transaction is created with the help of bitcoin core.
In the past I've seen a few instances where people got themselves in trouble by creating unexpected transactions, for example by paying 90% of the UTXO's value as a mining fee or the like.
Therefore I was wondering if someone could advise on procedures/tips for the following

Given a raw transaction T sending X BTC to address Z, how to validate the transaction accomplishes this gracefully?

The idea is that before the broadcast one issues an additional decoderawtransaction and checks that everything is as intended. I would like to hear tips on what one should check for at this point.
I understand the question itself is a bit vague but I'd like to hear any kind of feedback on what to look for in the output of decoderawtransaction that might be telling something is either not right, or validate that

The transaction is sending X BTC to Z,
What the exact expenditure (X+fees) is,
That the change is sent to the right (i.e under the wallet's control) address.
A very useful RPC is the testmempoolaccept RPC. This will tell you whether the transaction would be accepted by the node. You can use this to determine whether the transaction is correctly signed. It will also tell you what the transaction fee is so you can determine whether the fee is what you expect it to be. If the transaction would not be accepted, it will also tell you what went wrong.
To ensure that the transaction is logically correct (i.e. money is being sent to the right place), you can use decoderawtransaction and examine the contents of the vout array. Each output is in that array and the value for the output and the address, if any, will be listed. So you can scan that array and make sure that the intended recipients are there with the correct values.
It is harder to determine change, but if you know what the change address is and what the change value should be, then you can check it as if it were another recipient as described earlier.

One caveat about testmempoolaccept: it only works if the parent transactions are confirmed or in the mempool. The test it runs is on the mempool state at the time of the call, so it behaves as if you had done sendrawtransaction at that moment, except the part where the transaction is actually sent and added to the mempool.