> For the complete documentation index, see [llms.txt](https://docs.digit.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.digit.org/complaints-management/cms-v2.11/design/architecture/services/config-service.md).

# Config Service

digit-config-service

## Overview

A schema-validated, tenant-scoped configuration store for the DIGIT platform. It manages template bindings, provider credentials, and notification channel toggles used by the WhatsApp notification system.

### Key Functionalities

* **Schema validation** against MDMS v2 schemas before storing data.
* **Tenant fallback resolution** via `_resolve` API (`pg.citya` -> `pg` -> `*`).
* **Field-level encryption** for sensitive fields (e.g., auth tokens) marked with `x-security` in schema.
* **Unique constraint enforcement** via `x-unique` schema fields.
* **Flyway-managed** database migrations.

## Pre-requisites

Before you proceed with the configuration, make sure the following prerequisites are met:

* Java 17
* PostgreSQL 14+
* MDMS v2 Service (running at `localhost:8083` or configured via `MDMS_V2_HOST`)

## Data Model

#### Physical Data Model

The service uses a single table `eg_config_data` to store various configuration types as JSONB, validated by their respective schemas.

<table><thead><tr><th width="165.640625">type</th><th width="209.2734375">column</th><th>Description</th></tr></thead><tbody><tr><td>string</td><td>id</td><td>Unique record ID (UUID)</td></tr><tr><td>string</td><td>tenantid</td><td>Tenant identifier</td></tr><tr><td>string</td><td>schemacode</td><td>Schema type (e.g., TemplateBinding)</td></tr><tr><td>string</td><td>uniqueidentifier</td><td>Derived from x-unique fields</td></tr><tr><td>jsonb</td><td>data</td><td>Configuration payload</td></tr><tr><td>boolean</td><td>isactive</td><td>Record status</td></tr><tr><td>string</td><td>createdby</td><td>Audit field</td></tr><tr><td>string</td><td>lastmodifiedby</td><td>Audit field</td></tr><tr><td>bigint</td><td>createdtime</td><td>Epoch timestamp</td></tr><tr><td>bigint</td><td>lastmodifiedtime</td><td>Epoch timestamp</td></tr></tbody></table>

### Schema Setup

Before creating any configuration data, the respective schemas must be registered in the **MDMS v2 service**. The `digit-config-service` uses these to validate data and enforce constraints.

#### 1. NotificationChannel Schema

Toggles notification channels (WHATSAPP, SMS, EMAIL) and links them to providers.

```
{
  "type": "object",
  "title": "NotificationChannel",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "code",
    "name",
    "enabled"
  ],
  "x-unique": [
    "code"
  ],
  "properties": {
    "code": {
      "type": "string",
      "enum": [
        "WHATSAPP",
        "SMS",
        "EMAIL"
      ],
      "description": "Channel identifier"
    },
    "name": {
      "type": "string",
      "description": "Human-readable channel name"
    },
    "enabled": {
      "type": "boolean",
      "description": "Whether this channel is active for the tenant"
    },
    "providerName": {
      "type": "string",
      "description": "Provider handling this channel (links to ProviderDetail)"
    },
    "priority": {
      "type": "integer",
      "description": "Dispatch priority (lower = higher priority)"
    }
  },
  "additionalProperties": true
}
```

#### 2. ProviderDetail Schema

Stores credentials for notification providers (e.g., Twilio).

```
{
  "type": "object",
  "title": "ProviderDetail",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "providerName",
    "channel",
    "priority"
  ],
  "x-unique": [
    "providerName",
    "channel",
    "priority"
  ],
  "properties": {
    "channel": {
      "type": "string",
      "description": "Communication channel (whatsapp, sms, email)"
    },
    "isActive": {
      "type": "boolean",
      "default": true,
      "description": "Whether this provider is active"
    },
    "priority": {
      "type": "integer",
      "default": 0,
      "description": "Provider priority (lower = higher priority)"
    },
    "novuApiKey": {
      "type": "string",
      "description": "Optional provider-specific Novu API key"
    },
    "credentials": {
      "type": "object",
      "description": "Provider-specific credentials in Novu-compatible format"
    },
    "providerName": {
      "type": "string",
      "description": "Provider name (e.g., twilio, sendgrid, etc.)"
    }
  },
  "x-security": [
    "credentials",
    "novuApiKey"
  ],
  "description": "Schema for provider configurations per tenant and channel"
}
```

#### 3. TemplateBinding Schema

Maps domain events to specific templates and locales.

```
{
  "type": "object",
  "title": "TemplateBinding",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "eventName",
    "channel",
    "templateId",
    "locale"
  ],
  "x-unique": [
    "eventName",
    "channel",
    "locale"
  ],
  "properties": {
    "locale": {
      "type": "string",
      "default": "en_IN",
      "pattern": "^[a-z]{2}_[A-Z]{2}$",
      "description": "Locale code for provider (e.g., en_IN, hi_IN, en_US)"
    },
    "channel": {
      "type": "string",
      "description": "Communication channel (whatsapp, sms, email)"
    },
    "isActive": {
      "type": "boolean",
      "default": true,
      "description": "Whether this template binding is active"
    },
    "eventName": {
      "type": "string",
      "description": "Event name (e.g., COMPLAINTS.WORKFLOW.REJECT)"
    },
    "contentSid": {
      "type": "string",
      "description": "Provider-specific content SID (for Twilio)"
    },
    "novuApiKey": {
      "type": "string",
      "description": "Optional template-specific Novu API key"
    },
    "paramOrder": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Order of parameters for template"
    },
    "templateId": {
      "type": "string",
      "description": "Template identifier in Novu"
    },
    "requiredVars": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Required variables for template"
    }
  },
  "x-security": [
    "novuApiKey"
  ],
  "description": "Schema for template bindings per event and channel"
}
```

### API Endpoints

**Base path:** `/config-service/config/v1`

<table><thead><tr><th width="232.05078125">Endpoint</th><th width="144.5">Method</th><th>Description</th></tr></thead><tbody><tr><td><code>/_create/{schemaCode}</code></td><td>POST</td><td>Create a new config record</td></tr><tr><td><code>/_update/{schemaCode}</code></td><td>POST</td><td>Update an existing config record</td></tr><tr><td><code>/_search</code></td><td>POST</td><td>Search records with exact tenant match</td></tr><tr><td><code>/_resolve</code></td><td>POST</td><td>Resolve config with tenant hierarchy fallback</td></tr></tbody></table>

#### Resolve Logic (Fallback Mechanism)

The `/_resolve` API implements a hierarchical lookup:

1. **Specific Tenant:** e.g., `pg.citya`
2. **Parent Tenant:** e.g., `pg` (if not found in citya)
3. **Wildcard:** `*` (if not found in parent)

## Setup

#### Build & Run

```
mvn clean package -DskipTests

java -jar target/digit-config-service-0.1.0-SNAPSHOT.jar \
  --spring.datasource.url=jdbc:postgresql://localhost:5432/configdb \
  --spring.datasource.username=postgres \
  --spring.datasource.password=password
```

#### Configuration Properties

| Property                      | Default                 | Description                           |
| ----------------------------- | ----------------------- | ------------------------------------- |
| `server.servlet.context-path` | `/config-service`       | API context path                      |
| `mdms.v2.host`                | `http://localhost:8083` | MDMS v2 service host                  |
| `encryption.service.enabled`  | `false`                 | Enable/Disable field-level encryption |
| `state.level.tenantid`        | `pg`                    | Tenant ID used for encryption keys    |

***

#### Helm Chart

**Location:** [`deploy-as-code/helm/charts/common-services/digit-config-service`](https://github.com/egovernments/Citizen-Complaint-Resolution-System/tree/master/devops/deploy-as-code/charts/common-services/digit-config-service)

*For full API details, refer to the* [*OpenAPI Spec*](https://github.com/egovernments/Citizen-Complaint-Resolution-System/blob/master/docs/Configs_Service/config-service.openapi.yaml)*.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.digit.org/complaints-management/cms-v2.11/design/architecture/services/config-service.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
