This sounds earily familiar to a project I'm on right now. Bear with me, this is going to get thick....
We have a system that presents several different transactions to our associates for deductions and reimbursements from/to their paycheck. These transactions are rule-based, and can be dynamically assigned by record manipulation in a DB. What I did was create several tables: tblRules, tblRuleList, tblRuleXLAT
The first is the definition of the rule, and the ASP function that is linked to the rule. The second table is the list of rules and which transaction they are linked to. The last one, tblRuleXLAT (XLAT - Translation), contains values for the rules used by the rule functions themselves. This last one is optional.
When the associate logs on, I have a function that checks eligibility and returns back the ID of the transaction and whether their eligible or not. That eligibily function queries the DB for all active transactions and loops through them, and queries the tblRules joined against the tblRulesList tables to find out if there are any rules. If there are rules, I pull the rule function name from tblRules table and call it with the ASP function EVAL (There are two similar functions, EXEC and EVAL, not widely documented, they both execute ASP code in the fly. Not positive on the order of this, but one would evaluate the statement "a = b" as True (or False), the other would set the value of a to be the value of b).
Then I created a bunch of ASP functions called Rule Functions. The rule functions have a special naming convention and are in a special inc-ruleFuncs.asp include file. Each of my rule functions has several required parameters, such as a default value from tblRules, the rule that called it (so I can hit tblRulesXLAT for additional values), the transaction it's linked to, etc.
When the rule function returns to the eligibility function, it simply returns a True or False. If any transaction returned a False, then the entire transaction is ineligible, and any that return all True is eligible. A new array is built with all of the transaction IDs and their eligibility status. This array is returned to the calling page. That page can then loop through the final returned array to decide what to is available. I use the IDs of the "True" results in a query to get more detailed information to display on the page, and the "False" IDs I use to pull error messages from another function based on the failed rules so the user knows why they are ineligible.
Since only one rule can be called at a time I have a recordset for the eligibility function, and one for all of the rule functions to share.
I hope this gives you some ideas... it may not be the perfect route, but it works remarkably well for me...