01 — Service Decomposition
Status: ✅ Draft
Prerequisite: TD1, TD2
Next: 02 — API Design Standards
Breaks the 15 confirmed Core engines into individual microservices. For each service: runtime, responsibilities, data it reads from, data store type, open assumptions, and scale characteristics.
Runtime and language assignments are the working direction from TD1. Final assignments are confirmed by the Core team before each engine's build begins.
1. The 15 Core Services
All 15 engines confirmed in TD1 become individual microservices. Each runs as an independently deployable service behind the API Gateway. No module ever calls a service directly — all traffic enters through the gateway.
2. Service Catalogue
2.1 Identity Bridge
Runtime: Node.js
Path prefix: Internal — operates at the Gateway layer
Data store: None (stateless — validates tokens against ITS SSO in real time)
| Item | Detail |
|---|---|
| Responsibility | Intercepts every inbound request. Validates the ITS bearer token. Extracts and forwards itsId as a verified request header to downstream services. Rejects requests with missing or invalid tokens. |
| What it does NOT do | Does not issue tokens. Does not manage sessions. Does not replace ITS login — modules continue to handle user login via ITS SSO. |
| Data it reads from | ITS SSO — token validation endpoint (real-time call per request). No local data store. |
| Why Node.js | Every request passes through this service — must handle peak concurrency during Registration Open windows with minimal latency. |
| Scale characteristic | Horizontally scalable. Stateless — any instance handles any request. |
| Internal dependencies | Calls ITS SSO token validation endpoint. |
| Module-facing | Not callable directly. Transparent to modules — they send the token in Authorization; the gateway forwards X-Its-Id downstream. |
| Open assumptions / questions | ⚠️ ITS SSO token format not confirmed (C-001 pending ITS Technical session). Token validation latency SLA from ITS unknown — this affects gateway response time under peak load. Whether ITS supports token introspection or JWKS endpoint TBD. |
2.2 RBAC Engine
Runtime: Node.js
Path prefix: /v1/rbac/
Data store: Relational (role hierarchy, permission mappings, role assignments — requires relational joins across the 40+ level hierarchy)
| Item | Detail |
|---|---|
| Responsibility | Single permission authority for all 32 modules. Stores role definitions, role-to-permission mappings, and role assignments per itsId per scope. Evaluates permission checks at runtime. Platform Admin is the only write path — no module can write roles directly. |
| Data it reads from | Own relational store — role definitions, permission mappings, role assignments per itsId per miqaatId scope. itsId arrives as a verified header from Identity Bridge. |
| Why Node.js | Highest-frequency engine on the platform — called on every access boundary across 32 modules. Needs low-latency concurrent handling, not computation. |
| Scale characteristic | Horizontally scalable. Permission check results are deterministic — safe to cache with a short TTL (caching strategy under analysis). |
| Internal dependencies | Identity Bridge (verified itsId header) |
| Key endpoints | POST /v1/rbac/check · GET /v1/rbac/roles · POST /v1/rbac/assign (Platform Admin only) |
| Open assumptions / questions | ⚠️ How the 40+ hierarchy levels are modelled in the schema (flat table with parent references? nested sets? closure table?) — not yet decided. Caching strategy and TTL not confirmed — wrong cache TTL could serve stale permissions after a role is revoked. Whether role assignments support temporal scoping (a role that expires after the Miqaat closes) needs to be confirmed. |
2.3 Config Cascade Engine
Runtime: Node.js
Path prefix: /v1/config/
Data store: Key-value store with hierarchy support (hierarchical overrides: Global → Miqaat → type-specific context levels)
| Item | Detail |
|---|---|
| Responsibility | One change to a shared config key propagates to all modules automatically. Stores config at each level of the cascade. Returns the resolved effective value for a given key + miqaatId context. |
| Data it reads from | Own key-value store — config entries at Global, Miqaat, and type-specific context levels. Written by Platform Admin only. |
| Why Node.js | Fast hierarchical key-value lookups with aggressive caching. I/O bound — no computation. |
| Scale characteristic | Read-heavy. Highly cacheable. Write path is infrequent and Platform Admin only. |
| Internal dependencies | None at runtime. Read by all Core services and all modules. |
| Key endpoints | GET /v1/config/resolve · PUT /v1/config/set (Platform Admin only) |
| Open assumptions / questions | ⚠️ Key-value store technology not confirmed (Redis? DynamoDB? Postgres JSONB? — decision pending infrastructure session). Cache invalidation strategy when a config override is applied mid-miqaat is not defined. The intermediate context levels below Miqaat (e.g., City → Zone for Ashara, Phase → Session for Istefadah) are defined per Miqaat type — the schema for how these type-specific levels are stored and resolved needs to be designed. |
2.4 Miqaat Lifecycle Engine
Runtime: Node.js
Path prefix: /v1/miqaat/
Data store: Relational (miqaat state, phase transitions, structural config — requires auditability)
| Item | Detail |
|---|---|
| Responsibility | Creates, phases, configures, and archives Miqaats. A miqaatId does not exist until this engine creates it. No module can create or transition a Miqaat — only Core via Platform Admin. Owns the authoritative state of every active Miqaat. |
| Data it reads from | Own relational store — miqaat state, phase history, structural config per Miqaat type. Seeded at creation via Platform Admin. |
| Why Node.js | Primarily workflow state transitions and event publication — I/O and event-driven, not computation. |
| Scale characteristic | Low write frequency (lifecycle events are infrequent). Read-heavy — all modules query miqaat state. |
| Internal dependencies | Publishes lifecycle events to the Event Bus. Config Cascade Engine is seeded when a new Miqaat is created. |
| Key endpoints | POST /v1/miqaat · GET /v1/miqaat/{id} · POST /v1/miqaat/{id}/transition (Platform Admin only) |
| Open assumptions / questions | ⚠️ The valid phase transition state machine per Miqaat type is not fully defined — Ashara Mubaraka has different phases from Istefadah. Who defines the state machine for each Miqaat type, and is it configurable or hardcoded? What happens to active allocations when a Miqaat is archived or a phase is reversed? |
2.5 ITS Sync Engine
Runtime: FastAPI (Python)
Path prefix: /v1/its/
Data store: Relational (Core-held sync copy of 9 ITS-managed tables)
| Item | Detail |
|---|---|
| Responsibility | Full sync and delta sync of 9 ITS-managed tables into Core's internal read store. Feeds the Eligibility Engine, Allocation Engine, Zone Mapping Engine, and HR Bank. Modules that previously maintained their own ITS sync will decommission it and read from Core instead. |
| Data it reads from | ITS system — 9 ITS-managed tables (exact table names and schemas to be confirmed in the ITS Technical session). Writes into the Core ITS Read Store consumed by downstream engines. |
| Why FastAPI | ETL-like data transformation workload — data processing, not I/O. Python's data processing ecosystem is the natural fit. |
| Sync mechanism | Pull vs push vs hybrid — to be confirmed in the ITS Technical session (C-005 pending). |
| Scale characteristic | Batch-oriented during sync windows. Near-real-time delta sync required for eligibility decisions during live miqaats. |
| Internal dependencies | Writes into the shared ITS read store consumed by Eligibility Engine, Allocation Engine, Zone Mapping Engine, and HR Bank. |
| Key endpoints | GET /v1/its/mumin/{itsId} · GET /v1/its/sync/status |
| Open assumptions / questions | ⚠️ The exact 9 ITS tables, their schemas, and which fields Core needs are not confirmed — blocked on ITS Technical session. Sync mechanism (pull/push/hybrid) is the most critical open question (C-005). Conflict resolution strategy if ITS data changes between two sync windows is not defined. What happens to eligibility decisions in-flight when ITS sync is unavailable? ITS API rate limits and availability SLA are unknown. |
2.6 Eligibility Engine
Runtime: FastAPI (Python)
Path prefix: /v1/eligibility/
Data store: None (stateless evaluator — reads from other services at evaluation time)
| Item | Detail |
|---|---|
| Responsibility | Evaluates composite eligibility for a given itsId against a given Miqaat + rule set. Pulls from 4 data sources: ITS data (via sync store), prior attendance (HR Bank), learning records (ITS), and custom rules (Rule Engine). Returns a structured eligibility result — not a simple boolean. |
| Data it reads from | Rule Engine — rule definitions and composite rule config for this Miqaat. ITS sync store (via ITS Sync Engine) — mumin profile, demographic data. HR Bank — khidmat history and prior attendance. Config Cascade Engine — miqaat-specific eligibility config (which rule families apply). ITS learning records — how this is accessed (direct ITS call vs part of the 9 sync tables) is under analysis. |
| Why FastAPI | Complex rule evaluation across multiple data sources. Computational logic, not I/O. Python's expressive syntax suits composite conditional evaluation. |
| Scale characteristic | Stateless, horizontally scalable. Computationally intensive during bulk eligibility evaluation windows. |
| Internal dependencies | Rule Engine · ITS Sync Engine read store · HR Bank · Config Cascade Engine |
| Key endpoints | POST /v1/eligibility/check · GET /v1/eligibility/rules |
| Open assumptions / questions | ⚠️ Whether learning records are part of the 9 ITS sync tables or require a separate direct ITS call is not confirmed. How composite rules are chained (AND/OR/weighted logic) needs to be defined in the rule schema. Latency SLA for bulk eligibility checks (pre-processing a full Miqaat allocation) is unknown — this drives horizontal scaling decisions. Whether eligibility results are cached per itsId per miqaat, and if so cache invalidation when a rule changes mid-miqaat. |
2.7 Rule Engine
Runtime: FastAPI (Python)
Path prefix: /v1/rules/
Data store: Relational (rule definitions, rule families, composite rule configurations)
| Item | Detail |
|---|---|
| Responsibility | Stores and evaluates configurable business rules — eligibility criteria, filter logic, allocation conditions. Ops teams change rules here without engineer involvement. The 7 confirmed rule families from Day 5 sessions live here. Consumed by Eligibility Engine and Allocation Engine. |
| Data it reads from | Own relational store — rule definitions grouped into 7 rule families, composite rule configurations, per-miqaat rule activation records. Written by Platform Admin and authorised ops users only. |
| Why FastAPI | Business rule evaluation with complex conditional logic. Python's expressiveness and availability of rule evaluation libraries make this a natural fit. |
| Scale characteristic | Read-heavy at evaluation time. Rules change infrequently. Write path is Platform Admin + authorised ops only. |
| Internal dependencies | Called by Eligibility Engine and Allocation Engine. |
| Key endpoints | POST /v1/rules/evaluate · PUT /v1/rules/configure (Platform Admin only) |
| Open assumptions / questions | ⚠️ Rule engine library/framework not chosen (Python options: business-rules, durable-rules, custom expression evaluator). The exact schema for the 7 rule families from Day 5 needs to be defined. Rule versioning — can a rule be changed after allocation has started? If yes, do in-progress eligibility evaluations re-run? Who are the authorised ops users beyond Platform Admin — can module team leads configure their own rules? |
2.8 Allocation Engine
Runtime: FastAPI (Python)
Path prefix: /v1/allocation/
Data store: Relational with row-level locking (allocation state must be transactionally consistent — double-booking prevention is a hard requirement)
| Item | Detail |
|---|---|
| Responsibility | City seat allocation and capacity slot distribution. Modules submit allocation requests — this engine resolves them, prevents double-booking across all 32 modules, and maintains allocation state. The confirmed threat model (TD6) identifies allocation fraud as a primary attack surface — all allocation decisions go through a single code path here. |
| Data it reads from | Own relational store — current allocation state per miqaatId (seats taken, slots distributed). Rule Engine — allocation conditions and eligibility-gate rules. ITS sync store — mumin zone data for local/guest seat split. Miqaat Lifecycle Engine — miqaat capacity state and open/closed phase. |
| Why FastAPI | Optimisation algorithms for seat and slot distribution — computation-intensive resolution logic. |
| Scale characteristic | Horizontally scalable for reads. Write path must be serialised per miqaatId (row-level lock) to prevent race conditions during concurrent allocation requests. |
| Internal dependencies | Rule Engine · ITS Sync Engine read store · Miqaat Lifecycle Engine |
| Key endpoints | POST /v1/allocation/request · GET /v1/allocation/status |
| Open assumptions / questions | ⚠️ Optimisation algorithm for seat distribution not defined (first-come-first-served? priority-based? zone-quota weighted?). Waitlist handling — if seats are full, does Core manage a waitlist or return a denied response? What happens to allocations when Miqaat capacity is reduced after allocations are already made — rollback strategy not defined. Partial allocation failure handling (e.g., 3 of 4 requested slots filled) needs to be specified. |
2.9 Zone Mapping Engine
Runtime: FastAPI (Python)
Path prefix: /v1/zones/
Data store: Relational (ITS-sourced zone ↔ resident mappings, updated by ITS Sync Engine)
| Item | Detail |
|---|---|
| Responsibility | Source of truth for how many Mumineen belong to each zone. Feeds local vs guest splits for allocation decisions. Modules never compute zone counts themselves — they query Core. |
| Data it reads from | ITS sync store (via ITS Sync Engine) — zone-to-resident mappings from the relevant ITS tables. Updated whenever ITS Sync Engine processes zone-related changes. |
| Why FastAPI | Data aggregation from ITS sync data. Aggregation queries suit the Python ecosystem. |
| Scale characteristic | Read-heavy. Updated on each ITS sync cycle for zone-related tables. |
| Internal dependencies | ITS Sync Engine (data source) |
| Key endpoints | GET /v1/zones/resident-count · GET /v1/zones/mapping |
| Open assumptions / questions | ⚠️ Which of the 9 ITS sync tables contains zone-to-resident data is not confirmed — blocked on ITS Technical session. How zone boundaries are defined (geographic? administrative jamaat-based?) is not fully documented. How to handle Mumineen with no zone assigned or who are in transition between zones. Whether zone data is per-miqaat (a Mumin's zone at registration time) or always current ITS state. |
2.10 HR Bank
Runtime: FastAPI (Python)
Path prefix: /v1/hr/
Data store: Relational (cross-miqaat khidmat history per itsId — append-heavy, read by eligibility)
| Item | Detail |
|---|---|
| Responsibility | Platform-wide khidmat history across all miqaats and events. Enforces the one-primary-khidmat rule. Surfaces hidden talent for volunteer matching. Feeds the Eligibility Engine. Extension of the Mumin Info Aggregator identified in Day 2 sessions. |
| Data it reads from | ITS sync store (via ITS Sync Engine) — base mumin profile data. Event Bus — subscribes to khidmat completion events published by modules when khidmat is confirmed complete. Miqaat Lifecycle Engine — miqaat scope and phase (to correctly attribute khidmat to the right miqaat). |
| Why FastAPI | Data aggregation and cross-miqaat history computation — processing workload. |
| Scale characteristic | Append-heavy during miqaat operations (khidmat completions). Read-heavy by Eligibility Engine during evaluation windows. |
| Internal dependencies | ITS Sync Engine read store · Miqaat Lifecycle Engine · Event Bus (subscriber) |
| Key endpoints | GET /v1/hr/history/{itsId} · GET /v1/hr/quota |
| Open assumptions / questions | ⚠️ How khidmat records are written into HR Bank is not defined — does HR Bank subscribe to a module-published event (e.g., khidmat.completed)? Or do modules call an HR Bank write API? The event-based approach is preferred (consistent with the platform pattern) but the event schema is not yet defined. The exact definition and enforcement logic of the one-primary-khidmat rule needs to be specified — what counts as "primary" and who sets it. Whether historical khidmat data from pre-Core miqaats needs to be migrated in. |
2.11 Capacity Balance Engine
Runtime: FastAPI (Python)
Path prefix: /v1/capacity/
Data store: In-memory aggregation state (subscribes to events; no persistent primary store required)
| Item | Detail |
|---|---|
| Responsibility | Subscribes to capacity.configured events from all modules. Checks Vaaz venue / Mawaid / Kitchen capacity ratios. Publishes capacity.imbalance.detected when ratios are violated before a Miqaat goes live. Does not own any module's capacity data — it aggregates across module-published events. |
| Data it reads from | Event Bus — capacity.configured events published by each module when their venue/food/kitchen capacity is set. Miqaat Lifecycle Engine — miqaat state (to know if the Miqaat is in the pre-live phase where imbalance matters). |
| Why FastAPI | Ratio calculations and cross-module capacity aggregation — computational. |
| Scale characteristic | Event-driven. Triggered by event bus messages, not direct API calls. |
| Internal dependencies | Event Bus (subscriber) · Miqaat Lifecycle Engine |
| Key endpoints | GET /v1/capacity/status (used by Platform Admin dashboard) |
| Open assumptions / questions | ⚠️ The exact definition of "acceptable" Vaaz/Mawaid/Kitchen ratios is not documented — who defines the thresholds, and are they configurable per Miqaat or fixed platform constants? What action is taken beyond publishing capacity.imbalance.detected — does Platform Admin get an alert? Does the Miqaat lifecycle block until resolved? Whether in-memory aggregation state needs to survive a service restart (i.e., should it persist to a store or rebuild from event replay). |
2.12 Notification Dispatch Engine
Runtime: Node.js
Path prefix: /v1/notify/
Data store: Queue (outbound message queue per channel — delivery receipts tracked)
| Item | Detail |
|---|---|
| Responsibility | Platform-level notification delivery engine. Separate from ITS Comms (confirmed in Day 4 sessions — Core needs its own delivery engine). Accepts a notification request and fans out to the appropriate delivery channels (WhatsApp, email, SMS, push). Modules do not integrate with delivery channels directly. |
| Data it reads from | Config Cascade Engine — notification config per miqaat (active channels, template IDs, delivery windows). RBAC Engine — role-based audience resolution (when a notification targets a role group, not a specific itsId). Inbound request payload — notification content, target audience, channel preference from the calling module. |
| Why Node.js | Event-driven fan-out to multiple delivery channels. Naturally async I/O — Node.js non-blocking model is the right fit. |
| Scale characteristic | High throughput during broadcast windows. Queue-backed — spikes are absorbed without back-pressure on calling modules. |
| Internal dependencies | Config Cascade Engine · RBAC Engine |
| Key endpoints | POST /v1/notify |
| Open assumptions / questions | ⚠️ WhatsApp Business API integration specifics not confirmed — API version, account ownership (ITS-owned or Core-owned?), message template pre-approval process. Who owns and manages notification templates — Core team or each module team? Delivery receipt tracking and retry strategy (how many retries, dead-letter handling) not defined. Whether Core stores sent notification history or delegates to delivery channel receipts only. |
2.13 Task Engine
Runtime: Node.js
Path prefix: /v1/tasks/
Data store: Relational (task definitions, checklists, completion state)
| Item | Detail |
|---|---|
| Responsibility | Platform-level task and checklist definitions that span multiple modules or miqaat phases. Example: "Core contracts signed before Phase 0 closes." Module-specific operational checklists stay inside each module — not here. |
| Data it reads from | Own relational store — task definitions, per-miqaat task assignments, completion state per task per itsId or role. Miqaat Lifecycle Engine — phase context (which phase is active, which tasks are due). |
| Why Node.js | Workflow and checklist state management — primarily I/O and state transitions, not computation. |
| Scale characteristic | Low to medium frequency. Read-heavy during miqaat phase reviews. |
| Internal dependencies | Miqaat Lifecycle Engine (phase context) |
| Key endpoints | GET /v1/tasks · POST /v1/tasks/{id}/complete |
| Open assumptions / questions | ⚠️ Who creates platform-level tasks — is this Platform Admin only, or can Core team members define tasks without a code change? Whether tasks can have dependencies on each other (task B can only complete after task A) is not defined. Notification integration when tasks are overdue or a blocking task is not complete before a phase transition — not specified. |
2.14 Vendor Registry
Runtime: Node.js
Path prefix: /v1/vendors/, /v1/procurement/
Data store: Relational (shared vendor catalog, standard item codes, budget envelopes per miqaat)
| Item | Detail |
|---|---|
| Responsibility | Shared vendor catalog and standard item codes across all events and modules. Budget envelope guardrails — modules check against Core's budget ceiling before raising an indent. Cross-event vendor conflict detection. Modules own their own indent/approval workflows — Core owns the shared vendor data. |
| Data it reads from | Own relational store — shared vendor catalog, standard item codes, approved vendor list per category, budget envelopes per miqaatId. Config Cascade Engine — budget ceiling config per miqaat (overridable per miqaat at the cascade level). |
| Why Node.js | Primarily catalog lookups and I/O. Budget checks are threshold comparisons, not complex computation. |
| Scale characteristic | Read-heavy. Low write frequency. |
| Internal dependencies | Config Cascade Engine (budget config per miqaat) |
| Key endpoints | GET /v1/vendors · POST /v1/vendors (Platform Admin) · POST /v1/procurement/budget-check |
| Open assumptions / questions | ⚠️ How the shared vendor catalog is initially seeded — manual entry via Platform Admin, or migrated from an existing procurement system? The exact logic for cross-event conflict detection is not defined (what counts as a conflict — same vendor booked for overlapping dates across two miqaats?). Whether vendor data ever syncs from an external ERP or procurement system. Who has write access beyond Platform Admin (can a procurement coordinator add vendors?). |
2.15 Audit Log Backbone
Runtime: Node.js
Path prefix: /v1/audit/
Data store: Append-only log store (immutable — no update or delete operations, ever)
| Item | Detail |
|---|---|
| Responsibility | Immutable, append-only event stream. Every allocation decision, permission check, role change, config override, and miqaat phase transition is recorded. Cannot be modified or deleted — confirmed in TD6 as a hard platform requirement. Platform Admin can query; modules cannot write directly. |
| Data it reads from | All Core engines — every engine writes audit events to this service as a side-effect of its operations. Modules cannot write directly — only Core engines write audit entries. Queries are read-only, Platform Admin only. |
| Why Node.js | High write-throughput streaming append — Node.js non-blocking write model suits append-only log workloads. |
| Scale characteristic | Very high write throughput during live miqaat operations. Queries are infrequent (audit review, compliance) and can tolerate slightly higher latency. |
| Internal dependencies | All Core engines write audit events. |
| Key endpoints | POST /v1/audit (internal — Core services only) · GET /v1/audit/query (Platform Admin only) |
| Open assumptions / questions | ⚠️ Immutability mechanism not chosen — options include WORM (Write Once Read Many) storage, hash chaining (each entry references a hash of the previous), or a managed immutable log service. Retention period not defined (security session pending). Whether audit log storage is on the same infrastructure as operational data or air-gapped on separate storage. Real-time vs retrospective query model — can Platform Admin query live audit events, or is there a delay for indexing? |
3. ITS Sync Engine — Separate Service
The ITS Sync Engine has a different operational pattern from the request/response engines above. It is not called by modules. It runs on its own sync schedule, pulling from ITS and writing into Core's internal read store.
The sync mechanism (pull vs push vs hybrid) is under analysis — pending the ITS Technical session (C-005).
4. Domain Event Schema Registry
This is a platform component, not an engine in the same sense. It is a Node.js service that:
- Stores versioned JSON Schema definitions for all event types
- Validates schema conformance when an event is published to the bus
- Returns the schema for a given
eventType+schemaVersionon request
Data it reads from: Its own document store of versioned JSON schemas. Written by Core team via Platform Admin tooling — not editable by modules.
Open assumptions: Schema storage technology not confirmed (document store vs Postgres JSONB vs file-based). Whether the registry enforces schema validation synchronously at publish time (blocking) or asynchronously (non-blocking, flagging violations after the fact) — has a performance vs strictness tradeoff.
5. API Gateway Routing Table
The API Gateway routes inbound module requests by path prefix to the correct Core service. No module needs to know the internal address of any service.
| Path Prefix | Routes To | Auth Check |
|---|---|---|
/v1/rbac/ | RBAC Engine | API key + ITS token |
/v1/eligibility/ | Eligibility Engine | API key + ITS token |
/v1/rules/ | Rule Engine | API key + ITS token (read) · Platform Admin (write) |
/v1/miqaat/ | Miqaat Lifecycle Engine | Platform Admin only (write) · API key (read) |
/v1/config/ | Config Cascade Engine | API key + ITS token (read) · Platform Admin (write) |
/v1/allocation/ | Allocation Engine | API key + ITS token |
/v1/zones/ | Zone Mapping Engine | API key + ITS token |
/v1/hr/ | HR Bank | API key + ITS token |
/v1/capacity/ | Capacity Balance Engine | API key + ITS token |
/v1/notify/ | Notification Dispatch Engine | API key + ITS token |
/v1/tasks/ | Task Engine | API key + ITS token |
/v1/vendors/, /v1/procurement/ | Vendor Registry | API key + ITS token |
/v1/audit/query | Audit Log Backbone | Platform Admin only |
/v1/its/ | ITS Sync Engine | Internal / Platform Admin only |
Identity Bridge operates at the Gateway layer — it validates the ITS token before any routing decision is made.
6. Inter-Service Dependency Map
| Calling Service | Reads From | Reason |
|---|---|---|
| Eligibility Engine | Rule Engine | Fetch rule definitions to evaluate |
| Eligibility Engine | ITS Sync Engine read store | Mumin data (profile, demographics) |
| Eligibility Engine | HR Bank | Attendance and khidmat history |
| Eligibility Engine | Config Cascade Engine | Miqaat-specific eligibility config |
| Allocation Engine | Rule Engine | Allocation conditions |
| Allocation Engine | ITS Sync Engine read store | Zone data for seat calculation |
| Allocation Engine | Miqaat Lifecycle Engine | Miqaat capacity state |
| Capacity Balance Engine | Event Bus | Subscribes to capacity.configured events |
| Capacity Balance Engine | Miqaat Lifecycle Engine | Miqaat state |
| Notification Dispatch | Config Cascade Engine | Notification config per miqaat |
| Notification Dispatch | RBAC Engine | Audience targeting by role |
| Task Engine | Miqaat Lifecycle Engine | Phase context |
| Vendor Registry | Config Cascade Engine | Budget ceiling config per miqaat |
| HR Bank | ITS Sync Engine read store | Base mumin data |
| HR Bank | Event Bus | Subscribes to khidmat completion events |
| Miqaat Lifecycle Engine | Event Bus | Publishes lifecycle events |
| All engines | Audit Log Backbone | Write audit events |
Internal communication pattern (engine-to-engine): synchronous HTTP is the baseline. A more performant protocol (gRPC) is under analysis for the highest-frequency paths (Eligibility → Rule Engine, RBAC hot path).
7. Data Store Summary
| Service | Store Type | Writes From | Notes |
|---|---|---|---|
| Identity Bridge | None | — | Stateless |
| RBAC Engine | Relational | Platform Admin only | Role hierarchy joins; ACID required |
| Config Cascade Engine | Key-value with hierarchy | Platform Admin only | Fast reads; TTL cache layer above |
| Miqaat Lifecycle Engine | Relational | Platform Admin only | Auditability; phase transition history |
| ITS Sync Engine | Relational | ITS system (sync) | Core-held copy of 9 ITS tables |
| Eligibility Engine | None | — | Stateless evaluator |
| Rule Engine | Relational | Platform Admin + ops | Rule definitions; infrequent writes |
| Allocation Engine | Relational + row-level locking | Modules (via API) | Anti-double-booking; ACID critical |
| Zone Mapping Engine | Relational | ITS Sync Engine | ITS-sourced; updated on each sync |
| HR Bank | Relational | Event Bus (khidmat events) | Append-heavy; cross-miqaat history |
| Capacity Balance Engine | In-memory aggregation | Event Bus (capacity events) | No persistent primary store |
| Notification Dispatch | Queue | Modules (via API) | Delivery outbox per channel |
| Task Engine | Relational | Platform Admin + Core team | Task + checklist state |
| Vendor Registry | Relational | Platform Admin | Shared catalog; infrequent writes |
| Audit Log Backbone | Append-only log | All Core engines (internal) | Immutable; never updated or deleted |
| Domain Event Schema Registry | Document store | Core team tooling | Versioned JSON schemas |
Database technology per engine is under analysis. Each engine may use a different database product suited to its query patterns. Confirmed before each engine's build begins.
8. Open Assumptions Summary
A consolidated view of all open questions across the 15 services.
| Service | Open Question | Blocked On |
|---|---|---|
| Identity Bridge | ITS SSO token format and validation latency SLA | ITS Technical session (C-001) |
| Identity Bridge | Token introspection vs JWKS endpoint | ITS Technical session |
| RBAC Engine | Role hierarchy schema design (nested sets / closure table) | Core architecture session |
| RBAC Engine | Permission check caching strategy and TTL | Core architecture session |
| RBAC Engine | Temporal scoping for role assignments | Core architecture session |
| Config Cascade Engine | Key-value store technology | Infrastructure session |
| Config Cascade Engine | Cache invalidation on mid-miqaat config changes | Core architecture session |
| Config Cascade Engine | Type-specific context level schema | Core architecture session |
| Miqaat Lifecycle Engine | Phase transition state machine per Miqaat type | Business session |
| Miqaat Lifecycle Engine | Allocation rollback on Miqaat archive | Core architecture session |
| ITS Sync Engine | Sync mechanism (pull / push / hybrid) | ITS Technical session (C-005) |
| ITS Sync Engine | Exact 9 ITS table schemas | ITS Technical session |
| ITS Sync Engine | ITS API availability SLA and rate limits | ITS Technical session |
| Eligibility Engine | Learning records — sync table or direct ITS call | ITS Technical session |
| Eligibility Engine | Composite rule chaining logic (AND / OR / weighted) | Rule Engine design |
| Eligibility Engine | Bulk evaluation latency SLA | Load testing |
| Rule Engine | Rule engine library / framework | Core architecture session |
| Rule Engine | Rule versioning and in-flight re-evaluation | Core architecture session |
| Allocation Engine | Seat distribution algorithm | Business session |
| Allocation Engine | Waitlist handling | Business session |
| Allocation Engine | Partial allocation failure handling | Core architecture session |
| Zone Mapping Engine | Which ITS table holds zone data | ITS Technical session |
| Zone Mapping Engine | Zone definition (geographic vs administrative) | ITS Technical session |
| HR Bank | Khidmat write mechanism (event subscription vs API) | Core architecture session |
| HR Bank | One-primary-khidmat rule definition | Business session |
| HR Bank | Historical khidmat data migration | Migration planning |
| Capacity Balance Engine | Ratio thresholds (fixed vs configurable) | Business session |
| Capacity Balance Engine | In-memory state survival across restarts | Core architecture session |
| Notification Dispatch | WhatsApp Business API ownership and setup | ITS / Business session |
| Notification Dispatch | Template management ownership | Business session |
| Task Engine | Task creation access (Platform Admin only vs ops team) | Business session |
| Task Engine | Inter-task dependencies | Core architecture session |
| Vendor Registry | Vendor catalog seeding and migration | Business session |
| Vendor Registry | Cross-event conflict detection logic | Business session |
| Audit Log Backbone | Immutability mechanism (WORM / hash chain / managed service) | Security session |
| Audit Log Backbone | Retention period | Security session |
| Audit Log Backbone | Schema validation enforcement (sync vs async) | Core architecture session |
| Domain Event Schema Registry | Schema storage technology | Infrastructure session |