# Configuration System

## Overview

All adapter configuration comes from environment variables (or `.env` files). No YAML, JSON, or other config file formats are used. This keeps configuration simple and consistent with twelve-factor app practices.

## CoreSettings Base Class

The package provides `CoreSettings` with three base fields:

| Field | Type | Default | Description |
|---|---|---|---|
| `TENANT_NAME` | `str` | (required) | Name of the tenant |
| `ENV` | `str` | `"local"` | Environment name (local, staging, production) |
| `IS_TESTING` | `bool` | `True` | Whether running in test mode |

`IS_TESTING` defaults to `True` so that development environments are safe by default. Production deployments set `IS_TESTING=False` explicitly.

## Extending with TenantSettings

Adapters extend `CoreSettings` with their own fields:

```python
from entr_adapter_core.config import CoreSettings

class TenantSettings(CoreSettings):
    SAP_ENDPOINT: str
    SAP_API_KEY: str
    CUSTOM_TIMEOUT: int = 30
```

All fields are populated from environment variables or `.env` files. Required fields without defaults will raise a clear `ValidationError` if missing.

## Singleton Access Pattern

Use `@lru_cache()` to ensure a single settings instance across the application:

```python
from functools import lru_cache

@lru_cache()
def get_settings() -> TenantSettings:
    return TenantSettings()
```

The package does NOT provide `get_settings()` — adapters define it because they know their own `TenantSettings` class.

## Per-Handler Config Overrides

If a handler needs slightly different settings (e.g., different timeout):

```python
custom = self.settings.model_copy(update={"CUSTOM_TIMEOUT": 60})
```

This creates a new instance with the override. The original singleton is not mutated.

## Error Handling

When a required field is missing, Pydantic raises a `ValidationError` with a clear message:

```
pydantic_core._pydantic_core.ValidationError: 1 validation error for TenantSettings
SAP_ENDPOINT
  Field required [type=missing, input_value={}, input_type=dict]
```

The framework does not wrap or obscure this error. It clearly identifies which variable is missing.

## Security

- **`CoreSettings` contains NO secrets** — only base fields shared across all adapters
- **All tenant-specific credentials belong in `TenantSettings`** — API keys, database URIs, etc.
- **`.env` files should be in `.gitignore`** — never commit secrets to version control
- Environment variables take precedence over `.env` file values
