Two automations, one shared setting — a lesson in ownership
Context
Two separate, independent pieces of automation each manage their own identity system in this homelab — one for accounts I use myself, one dedicated to outside visitors. Both, it turned out, were writing to the very same piece of shared configuration that tells the portal which identity system to actually trust.
The problem
One evening, an automation run motivated by a completely unrelated task — creating a personal account on the internal identity system — silently overwrote that shared configuration back to the internal system's settings, undoing a switch to the external system made that same morning. Nobody noticed for several days, because the portal kept working the whole time — just authenticating against the wrong identity system, invisibly.
Diagnosing it properly
Rather than trust the first plausible explanation, the actual state was cross-checked three independent ways: querying both identity databases directly, querying both systems' own management interfaces, and inspecting the value the running service was actually using — not just what a configuration file claimed. All three converged on the same conclusion, which is what made the fix trustworthy rather than a guess.
The real lesson
Two automated systems that both write the same shared object, with no coordination and no explicit ownership, produce a particularly sneaky class of bug: every individual run "succeeds" — no error, no failed step — and yet the final result depends entirely on which one ran last, something invisible from reading either system's code in isolation.
The fix wasn't a check added after the fact. It was making ownership of that shared object explicit and enforced at the source: a flag that must be deliberately set before either automation is even allowed to touch it, replacing what had been an unwritten, easily-forgotten convention ("we just don't touch what the other one manages"). A dependency accidentally becomes obvious the moment you have to name it out loud in code.
Alternatives considered
- A single identity system with two logical partitions instead of two fully separate ones — rejected before this incident even happened, on unrelated grounds: it would have removed the network-level isolation between "my own trusted accounts" and "an outside visitor's account," which matters more than the convenience of one system to manage.
- A quick, temporary workaround (a manual tunnel) to unblock testing while the real fix was designed — considered, then dropped in favor of solving the actual routing gap properly, since a "temporary" workaround has a way of outliving its justification.
Why it's worth telling
This isn't really a story about identity systems. It's a story about what happens when two pieces of automation, built at different times for different reasons, quietly share one piece of state with nobody assigned to own it. That pattern shows up everywhere automation grows organically — not just here.