Skip to main content

Config Service — Service Overview

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD


1. Purpose

The config-service is the single authoritative resolver for runtime configuration state across the entire Ghasi eHealth platform. Every service and frontend client calls it to answer the compound question:

"Given user U at facility node N, for module M, feature F, and action A: is the action permitted, what UI elements are visible, and which design tokens apply?"

It traverses a Directed Acyclic Graph (DAG) that encodes the full configuration inheritance chain from platform global defaults down to per-user overrides, resolving licensing, RBAC, ABAC, UI visibility, and design tokens in a single call.


2. Bounded Context

AspectDetail
DDD contextPlatform Configuration
Service registry03-platform-services.md
Internal base URLhttp://config-service:3015
Admin base URL (via Kong)https://api.ghasi-health.af/api/config
Package name@ghasi/service-config

3. Responsibilities

ResponsibilityNotes
Runtime config resolution — 9-step pipelineLicense → feature flag → role graph → ABAC → user overrides → UI → tokens
ConfigNode DAG management13 node types; acyclic invariant enforced at write time
Feature definition CRUDPer-tenant features with allowedActions and dataScopeType
Role definition + inheritance graphBFS expansion, max depth 10, cycle detection at definition time
Role feature grantsgrantedActions / deniedActions per role per feature
User node overridesExplicitAllow / ExplicitDeny at any hierarchy node scope
UI element visibility configurationPer role and per user, optionally scoped to a node
Design token managementGlobal → Tenant → OrgNode → Module → User merge chain with LWW
Redis cache with TTL + event-driven invalidationNamespace cfg:*; eviction triggered by NATS mutation events
Audit event emissionAll mutations; 1 % sampling on resolution calls for diagnostics

4. Non-Responsibilities

Not owned hereOwned by
JWT issuance and OIDC flowsKeycloak / identity-service
Base RBAC role assignment CRUDidentity-service
ABAC policy definition + evaluation endpointaccess-policy (POST /internal/access/evaluate)
FHIR resource-level consent enforcementfuture consent service
Kong routing, rate limiting, auth gatewayKong
Secrets and KMS key managementKMS + env vars
Hierarchy node CRUD (org structure)facility-service
Module license CRUDplatform-admin-service
Tenant branding primitive storage (logoUrl, etc.)tenant-service

5. Resolution Inheritance Chain

Global → Tenant → OrgNode → Module → Feature → Action
→ Role (+ inheritance) → User override
→ UIScreen → UIComponent → UIElement → ActionBinding
→ DesignSystem tokens

6. Resolution Algorithm — 9-Step Flow


7. Upstream / Downstream Dependencies

DependencyDirectionPurpose
facility-serviceoutbound HTTPHierarchy spine + node ancestor chain (Step 1)
platform-admin-serviceoutbound HTTPModule license check (Step 2) + feature flag (Step 3)
access-policyoutbound HTTPABAC policy evaluation (Step 6)
identity-serviceoutbound HTTPUser membership validation for override creation
RedisinfrastructureTTL cache + event-driven invalidation
NATS JetStreamoutbound eventsConfig mutation audit events
audit-serviceevent consumerPersists all mutation audit records
Every platform serviceinbound API consumerGET /internal/config/resolve per request
Frontend SDK (@ghasi/ui-config-client)inbound API consumeruseConfigResolution() hook via BFF

8. Platform Gap Resolution

Gap IDDescriptionConfig-service solution
L-01Feature flags were binary; no per-feature data-scope configFeatureDefinition.dataScopeType enum
L-02ABAC policies were JSONB blobs, not composableDAG node model + delegation to access-policy
L-03No role inheritance (Nurse ≠ ClinicalStaff)RoleInheritance edges + BFS expansion
L-04No UI visibility config per role/userUIVisibilityRule + UIDefinition
L-05No design system theming at module/user levelDesignToken scope chain with LWW merge
L-06Every UI boundary made 5–7 API callsSingle GET /internal/config/resolve
L-07No user-level explicit allow/denyUserNodeOverride aggregate
L-08DataScope not first-classFeatureDefinition.dataScopeType
L-09No action bindings to UI elementsACTION_BINDING node type

9. Key Architectural Decisions

DecisionRationale
Single compound resolution endpointEliminates N-call fan-out; one cache key per session context
DAG over flat key-value storeEnables inheritance, composability, and auditable ancestry
Redis cache with event-driven evictionp95 < 50 ms target; correctness maintained via NATS mutation events
Delegate ABAC to access-policy serviceSingle ownership of ABAC contract; no parallel evaluate surface
Soft-delete only on ConfigNodesAudit integrity; hard-delete rejected with 405
BFS role graph max depth 10Prevents unbounded traversal; depth violation rejected at definition time
tenantId only from JWT claimsNever from query params or body in user-facing path

10. Source Reconciliation

Single source module: services/config-service/_sources/config-resolver/. No multi-module merge was required. Legacy module ID PLAT-CONFIG is preserved in legacy FR references; all new identifiers use the CONFIG-* prefix per the platform ID registry.