Skip to main content

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)

ItemDetail
ResponsibilityIntercepts 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 doDoes not issue tokens. Does not manage sessions. Does not replace ITS login — modules continue to handle user login via ITS SSO.
Data it reads fromITS SSO — token validation endpoint (real-time call per request). No local data store.
Why Node.jsEvery request passes through this service — must handle peak concurrency during Registration Open windows with minimal latency.
Scale characteristicHorizontally scalable. Stateless — any instance handles any request.
Internal dependenciesCalls ITS SSO token validation endpoint.
Module-facingNot 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)

ItemDetail
ResponsibilitySingle 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 fromOwn relational store — role definitions, permission mappings, role assignments per itsId per miqaatId scope. itsId arrives as a verified header from Identity Bridge.
Why Node.jsHighest-frequency engine on the platform — called on every access boundary across 32 modules. Needs low-latency concurrent handling, not computation.
Scale characteristicHorizontally scalable. Permission check results are deterministic — safe to cache with a short TTL (caching strategy under analysis).
Internal dependenciesIdentity Bridge (verified itsId header)
Key endpointsPOST /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)

ItemDetail
ResponsibilityOne 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 fromOwn key-value store — config entries at Global, Miqaat, and type-specific context levels. Written by Platform Admin only.
Why Node.jsFast hierarchical key-value lookups with aggressive caching. I/O bound — no computation.
Scale characteristicRead-heavy. Highly cacheable. Write path is infrequent and Platform Admin only.
Internal dependenciesNone at runtime. Read by all Core services and all modules.
Key endpointsGET /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)

ItemDetail
ResponsibilityCreates, 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 fromOwn relational store — miqaat state, phase history, structural config per Miqaat type. Seeded at creation via Platform Admin.
Why Node.jsPrimarily workflow state transitions and event publication — I/O and event-driven, not computation.
Scale characteristicLow write frequency (lifecycle events are infrequent). Read-heavy — all modules query miqaat state.
Internal dependenciesPublishes lifecycle events to the Event Bus. Config Cascade Engine is seeded when a new Miqaat is created.
Key endpointsPOST /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)

ItemDetail
ResponsibilityFull 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 fromITS 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 FastAPIETL-like data transformation workload — data processing, not I/O. Python's data processing ecosystem is the natural fit.
Sync mechanismPull vs push vs hybrid — to be confirmed in the ITS Technical session (C-005 pending).
Scale characteristicBatch-oriented during sync windows. Near-real-time delta sync required for eligibility decisions during live miqaats.
Internal dependenciesWrites into the shared ITS read store consumed by Eligibility Engine, Allocation Engine, Zone Mapping Engine, and HR Bank.
Key endpointsGET /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)

ItemDetail
ResponsibilityEvaluates 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 fromRule 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 FastAPIComplex rule evaluation across multiple data sources. Computational logic, not I/O. Python's expressive syntax suits composite conditional evaluation.
Scale characteristicStateless, horizontally scalable. Computationally intensive during bulk eligibility evaluation windows.
Internal dependenciesRule Engine · ITS Sync Engine read store · HR Bank · Config Cascade Engine
Key endpointsPOST /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)

ItemDetail
ResponsibilityStores 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 fromOwn 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 FastAPIBusiness rule evaluation with complex conditional logic. Python's expressiveness and availability of rule evaluation libraries make this a natural fit.
Scale characteristicRead-heavy at evaluation time. Rules change infrequently. Write path is Platform Admin + authorised ops only.
Internal dependenciesCalled by Eligibility Engine and Allocation Engine.
Key endpointsPOST /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)

ItemDetail
ResponsibilityCity 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 fromOwn 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 FastAPIOptimisation algorithms for seat and slot distribution — computation-intensive resolution logic.
Scale characteristicHorizontally scalable for reads. Write path must be serialised per miqaatId (row-level lock) to prevent race conditions during concurrent allocation requests.
Internal dependenciesRule Engine · ITS Sync Engine read store · Miqaat Lifecycle Engine
Key endpointsPOST /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)

ItemDetail
ResponsibilitySource 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 fromITS 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 FastAPIData aggregation from ITS sync data. Aggregation queries suit the Python ecosystem.
Scale characteristicRead-heavy. Updated on each ITS sync cycle for zone-related tables.
Internal dependenciesITS Sync Engine (data source)
Key endpointsGET /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)

ItemDetail
ResponsibilityPlatform-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 fromITS 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 FastAPIData aggregation and cross-miqaat history computation — processing workload.
Scale characteristicAppend-heavy during miqaat operations (khidmat completions). Read-heavy by Eligibility Engine during evaluation windows.
Internal dependenciesITS Sync Engine read store · Miqaat Lifecycle Engine · Event Bus (subscriber)
Key endpointsGET /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)

ItemDetail
ResponsibilitySubscribes 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 fromEvent Buscapacity.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 FastAPIRatio calculations and cross-module capacity aggregation — computational.
Scale characteristicEvent-driven. Triggered by event bus messages, not direct API calls.
Internal dependenciesEvent Bus (subscriber) · Miqaat Lifecycle Engine
Key endpointsGET /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)

ItemDetail
ResponsibilityPlatform-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 fromConfig 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.jsEvent-driven fan-out to multiple delivery channels. Naturally async I/O — Node.js non-blocking model is the right fit.
Scale characteristicHigh throughput during broadcast windows. Queue-backed — spikes are absorbed without back-pressure on calling modules.
Internal dependenciesConfig Cascade Engine · RBAC Engine
Key endpointsPOST /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)

ItemDetail
ResponsibilityPlatform-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 fromOwn 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.jsWorkflow and checklist state management — primarily I/O and state transitions, not computation.
Scale characteristicLow to medium frequency. Read-heavy during miqaat phase reviews.
Internal dependenciesMiqaat Lifecycle Engine (phase context)
Key endpointsGET /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)

ItemDetail
ResponsibilityShared 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 fromOwn 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.jsPrimarily catalog lookups and I/O. Budget checks are threshold comparisons, not complex computation.
Scale characteristicRead-heavy. Low write frequency.
Internal dependenciesConfig Cascade Engine (budget config per miqaat)
Key endpointsGET /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)

ItemDetail
ResponsibilityImmutable, 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 fromAll 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.jsHigh write-throughput streaming append — Node.js non-blocking write model suits append-only log workloads.
Scale characteristicVery high write throughput during live miqaat operations. Queries are infrequent (audit review, compliance) and can tolerate slightly higher latency.
Internal dependenciesAll Core engines write audit events.
Key endpointsPOST /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 + schemaVersion on 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 PrefixRoutes ToAuth Check
/v1/rbac/RBAC EngineAPI key + ITS token
/v1/eligibility/Eligibility EngineAPI key + ITS token
/v1/rules/Rule EngineAPI key + ITS token (read) · Platform Admin (write)
/v1/miqaat/Miqaat Lifecycle EnginePlatform Admin only (write) · API key (read)
/v1/config/Config Cascade EngineAPI key + ITS token (read) · Platform Admin (write)
/v1/allocation/Allocation EngineAPI key + ITS token
/v1/zones/Zone Mapping EngineAPI key + ITS token
/v1/hr/HR BankAPI key + ITS token
/v1/capacity/Capacity Balance EngineAPI key + ITS token
/v1/notify/Notification Dispatch EngineAPI key + ITS token
/v1/tasks/Task EngineAPI key + ITS token
/v1/vendors/, /v1/procurement/Vendor RegistryAPI key + ITS token
/v1/audit/queryAudit Log BackbonePlatform Admin only
/v1/its/ITS Sync EngineInternal / 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 ServiceReads FromReason
Eligibility EngineRule EngineFetch rule definitions to evaluate
Eligibility EngineITS Sync Engine read storeMumin data (profile, demographics)
Eligibility EngineHR BankAttendance and khidmat history
Eligibility EngineConfig Cascade EngineMiqaat-specific eligibility config
Allocation EngineRule EngineAllocation conditions
Allocation EngineITS Sync Engine read storeZone data for seat calculation
Allocation EngineMiqaat Lifecycle EngineMiqaat capacity state
Capacity Balance EngineEvent BusSubscribes to capacity.configured events
Capacity Balance EngineMiqaat Lifecycle EngineMiqaat state
Notification DispatchConfig Cascade EngineNotification config per miqaat
Notification DispatchRBAC EngineAudience targeting by role
Task EngineMiqaat Lifecycle EnginePhase context
Vendor RegistryConfig Cascade EngineBudget ceiling config per miqaat
HR BankITS Sync Engine read storeBase mumin data
HR BankEvent BusSubscribes to khidmat completion events
Miqaat Lifecycle EngineEvent BusPublishes lifecycle events
All enginesAudit Log BackboneWrite 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

ServiceStore TypeWrites FromNotes
Identity BridgeNoneStateless
RBAC EngineRelationalPlatform Admin onlyRole hierarchy joins; ACID required
Config Cascade EngineKey-value with hierarchyPlatform Admin onlyFast reads; TTL cache layer above
Miqaat Lifecycle EngineRelationalPlatform Admin onlyAuditability; phase transition history
ITS Sync EngineRelationalITS system (sync)Core-held copy of 9 ITS tables
Eligibility EngineNoneStateless evaluator
Rule EngineRelationalPlatform Admin + opsRule definitions; infrequent writes
Allocation EngineRelational + row-level lockingModules (via API)Anti-double-booking; ACID critical
Zone Mapping EngineRelationalITS Sync EngineITS-sourced; updated on each sync
HR BankRelationalEvent Bus (khidmat events)Append-heavy; cross-miqaat history
Capacity Balance EngineIn-memory aggregationEvent Bus (capacity events)No persistent primary store
Notification DispatchQueueModules (via API)Delivery outbox per channel
Task EngineRelationalPlatform Admin + Core teamTask + checklist state
Vendor RegistryRelationalPlatform AdminShared catalog; infrequent writes
Audit Log BackboneAppend-only logAll Core engines (internal)Immutable; never updated or deleted
Domain Event Schema RegistryDocument storeCore team toolingVersioned 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.

ServiceOpen QuestionBlocked On
Identity BridgeITS SSO token format and validation latency SLAITS Technical session (C-001)
Identity BridgeToken introspection vs JWKS endpointITS Technical session
RBAC EngineRole hierarchy schema design (nested sets / closure table)Core architecture session
RBAC EnginePermission check caching strategy and TTLCore architecture session
RBAC EngineTemporal scoping for role assignmentsCore architecture session
Config Cascade EngineKey-value store technologyInfrastructure session
Config Cascade EngineCache invalidation on mid-miqaat config changesCore architecture session
Config Cascade EngineType-specific context level schemaCore architecture session
Miqaat Lifecycle EnginePhase transition state machine per Miqaat typeBusiness session
Miqaat Lifecycle EngineAllocation rollback on Miqaat archiveCore architecture session
ITS Sync EngineSync mechanism (pull / push / hybrid)ITS Technical session (C-005)
ITS Sync EngineExact 9 ITS table schemasITS Technical session
ITS Sync EngineITS API availability SLA and rate limitsITS Technical session
Eligibility EngineLearning records — sync table or direct ITS callITS Technical session
Eligibility EngineComposite rule chaining logic (AND / OR / weighted)Rule Engine design
Eligibility EngineBulk evaluation latency SLALoad testing
Rule EngineRule engine library / frameworkCore architecture session
Rule EngineRule versioning and in-flight re-evaluationCore architecture session
Allocation EngineSeat distribution algorithmBusiness session
Allocation EngineWaitlist handlingBusiness session
Allocation EnginePartial allocation failure handlingCore architecture session
Zone Mapping EngineWhich ITS table holds zone dataITS Technical session
Zone Mapping EngineZone definition (geographic vs administrative)ITS Technical session
HR BankKhidmat write mechanism (event subscription vs API)Core architecture session
HR BankOne-primary-khidmat rule definitionBusiness session
HR BankHistorical khidmat data migrationMigration planning
Capacity Balance EngineRatio thresholds (fixed vs configurable)Business session
Capacity Balance EngineIn-memory state survival across restartsCore architecture session
Notification DispatchWhatsApp Business API ownership and setupITS / Business session
Notification DispatchTemplate management ownershipBusiness session
Task EngineTask creation access (Platform Admin only vs ops team)Business session
Task EngineInter-task dependenciesCore architecture session
Vendor RegistryVendor catalog seeding and migrationBusiness session
Vendor RegistryCross-event conflict detection logicBusiness session
Audit Log BackboneImmutability mechanism (WORM / hash chain / managed service)Security session
Audit Log BackboneRetention periodSecurity session
Audit Log BackboneSchema validation enforcement (sync vs async)Core architecture session
Domain Event Schema RegistrySchema storage technologyInfrastructure session