For models that can be joined into a solid It would be not that difficult to join a copy of the inputs into a solid and check each input if the normal is aligned with the newly created solid ( and flip if needed).
For cases with not closed input I see an option to still join into polysurface.
That new polysurface is probably easier analyzed for the normal being correct than the separate surfaces.
Once you have ensured the polysurface has the correct orientation you can do as above and check inputs against the polysurface.
In any case, determining the ‘correct’ orientation you need the know the topological relationship between the separate surfaces.
eg for a vertical surface you need to know what other surfaces it connects to, to define the correct orientation.
I think to tackle the non solid input cases you need to know the ‘type of openness’ -for lack of better wording-
Say if these open sides are always on the bottom you can infer the correct orientation from the top most flat most surface and work downward from there…
If you are going to give it a shot, make sure not to get caught by the flipping flag of orientations as mentioned before and the possibility of inward facing solids. IIRC Evaluating a face surface with reversed orientation can yield a different normal as the PolySurface it describes.
I leave the code snipped below as possible checks/solutions
Disclaimer I quicky dug these up in our codebase, make sure to test and evaluate properly.
if brep.SolidOrientation == Rhino.Geometry.BrepSolidOrientation.Inward:
for face in brep.Faces:
# print face.OrientationIsReversed