Condition Builder
Lumos · 2025
Timeframe: Discovery to GA, 3 months
Lumos is an identity and access platform. Almost every product in it eventually needs to say the same thing: this rule for these people. Access policies say it, approval rules say it, lifecycle management workflows say it - you get it. Over time, each one had been built when it was needed, by whichever team needed it.
TL;DR
Our existing product areas had each developed their own way to describe a set of users. They worked individually, but users needed to constantly learn new patterns and hit different limitations. There's a generic need nobody had named yet: admins want to control how the product behaves for different sets of people, everywhere, and that need kept arriving in new surface areas.
I built a conditional-logic primitive, adopted across three areas, and added an evaluation mode so an admin can test a rule against real data and see exactly who it matches before applying it.
Challenges & Opportunities
Building a bespoke experience per area was compounding costs in different aspects:
- Inconsistent capability - Conditional logic and expression-language support differed per area, because each team had implemented its own
- Duplicated effort - Every team maintained their own version of the same thing
- Nobody met the enterprise bar - Nested boolean logic was beyond all four implementations
Solving this problem will give us two tangible outcomes:
- Unblock important deals - Some deals stalled on rules the product couldn't express; conditions were the named blocker on several enterprise opportunities
- Admins are able to verify the rules they write - Imagine saving a rule governing who gets access to what, and then having to wait to find out if something goes wrong
Key bets
01Let's speak a shared language!
What exactly is a condition? A condition group? An operator? These sound like pedantic questions until I noticed that three teams were using the same word for different things. I pinned down the anatomy of a condition and mapped every operator we'd need to support, before any UI existed.
This exercise gave the team a shared language, and we were able to use them to ground decisions in a system.
02Realistic prototypes are make or break
For a component like this, static mocks can be a lie. An idealised two-condition example always looks fine, but the risks are in the messiness and complexity that exist in the real world - where a rule is eight conditions deep and nested two groups down.
So rather than iterating in Figma, I built realistic working prototypes thanks to AI, and put them in front of people early. That was the only way to find where the pattern fell apart.
03A primitive is only real once other teams adopt it
We made a deliberate call not to migrate existing features onto the new framework. One reason was timing; the other is that we believed adoption had to be earned instead - everyone else would choose it because it was the best option available, not because they had been told to.
After handoff I stayed close to every surface that adopted it. I bug bashed the component in each product area and collected the inconsistencies in one place, so the platform team could push fixes up to the component level rather than letting each team patch its own copy.
I'm proud to say this condition builder now backs pre-approval rules for AppStore, scoping for Access Review, on and offboarding for LCM - and many other surfaces. The features that predated the framework have been migrating onto it since, organically. That is the only real proof that a platform primitive landed.
Impact
The conditional logic pattern shipped as a platform primitive rather than a feature, and was adopted across many surfaces. The three where it had the biggest impact:
- AppStore: attribute-based approvals - Routing approvals by who the requester is, which is what large prospects kept asking for before they'd commit
- Lifecycle management: access policies - Complex access rules, the specific blocker holding up several enterprise deals
- Lifecycle management: conditional on/offboarding - Unified logic across both, meeting enterprise requirements with the same component rather than a fourth variant of it
In each case we saw a similar pattern: conditions stopped being the reason a deal stalled. The approach outlasted the project too - we reused the same primitive-first approach later when building a more advanced filter system.