You're basically correct.
The basic unit is the rule, which contains your business logic. You collect your business logic rules into a KieBase. Optimally, each KieBase would be a discrete collection of related rules -- for example, you could have a KieBase that contains validation rules for inbound requests, and another KieBase that contains rules for monitoring events from an alarm system.
When you decide to fire rules, you'd identify which KieBase(s) contain the logic you want to invoke, then request a session against them. The api will return an appropriate session (stateless or stateful), to which you'd add your input data and fire the rules.
From the documentation:
The KieBase is a repository of all the application’s knowledge definitions. It will contain rules, processes, functions, and type models. The KieBase itself does not contain data; instead, sessions are created from the KieBase into which data can be inserted and from which process instances may be started. The KieBase can be obtained from the KieContainer containing the KieModule where the KieBase has been defined.
KieContainer and KieModule are a little harder to differentiate, but they're basically the same thing in practice (container being the runtime implementation, module being the specification.) There's technical reasons they're discrete entities, but you'll rarely (if ever) deal with both at the same time. They both simply contain KieBases and any configuration for sessions, timers, etc. (the kiebase runtime, effectively.)
As a more practical example, let's say we have an application for elementary school administrators. We have several different categories of rules: tracking student tardiness and issuing demerits for excessive absences; assigning grades for classes; and tracking inventory of school supplies.
We'd organize our rules into three KieBases:
- attendance and tardiness
- grades
- inventory
When we start up the application, we'd load all of our rules either from a repository via a kjar, or local in-memory rules. These would be loaded as KieModules. The various KBases would then be compiled and read into memory.
We'd retain a reference to the KieServices, or possibly the KieContainer, depending on whether you have multiple modules or just a single one holding all the KieBases. (Recall that at runtime, we deal with the KieContainer, not the KieModule, which is the abstraction.)
When our application needs to fire a specific type of rules, we'd fetch the KieBase from the KieServices (via the KieContainer), request a session, and fire the rules. So if we're in the bit of the application that deals with inventory management, we'd fetch out the KieBase containing the relevant inventory rules, get a session, and fire it.
(Note that you can get a session against either a KieContainer or a KieBase. This wasn't part of your question, though.)