Stats are stored as bytes but inconsistently read as signed and unsigned numbers, and as such any value over 127 is going to in some cases be read as negative. This then makes HP cap at 127, but all other stats will also cap here. While the game is running each stat is, as stated, stored as a byte and as such can be any value from 0-255; since anything over 127 is read as signed, that’s still the cap on every stat. The problems start when saving and loading units. In vanilla, to save on space, non-HP stats get bitpacked down to 5 bits; a 5-bit value can store 2^5=32 values, which as this includes 0 makes a cap of 31. Similarly, item durability gets bitpacked to a 6-bit value or 2^6=64 values and a cap of 63. Both of these limits can be removed, however, with the use of engine hacks:
Expanded Modular Save changes the unit save & load functions such that stats and item durability save the entire byte, giving you the full range of values at your disposal of 127 caps on all stats and 255 cap on durability.
Max recruited characters is a bit of a different situation. There is space in memory dedicated to player units large enough to store 63 units, which makes that technically the cap without moving where player units are located in memory. However, as the game does not expect you to ever get this high, once you’re over 50 units a lot of small things will break in one way or another. Some hacks like Vision Quest have mitigated these issues, though I’m unsure if said mitigations have been released publically.