# Domain Module

The `pycharter.domain` module provides utilities for working with **lifecycle bindings** declared in domain-entity contracts. It is engine-agnostic: it reads the convention from the contract metadata and returns structured data that callers can pass to any FSM engine (e.g. [PyStator](https://github.com/optophi/pystator)).

See [Domain Models and Lifecycle](../guides/domain-models-and-lifecycle.md) for the full guide.

## Functions

::: pycharter.domain.get_lifecycle_binding
    options:
      show_root_heading: true
      heading_level: 3

::: pycharter.domain.get_domain_entity_info
    options:
      show_root_heading: true
      heading_level: 3

::: pycharter.domain.check_state_alignment
    options:
      show_root_heading: true
      heading_level: 3

::: pycharter.domain.validate_lifecycle_binding
    options:
      show_root_heading: true
      heading_level: 3

## Constants

| Name | Default | Description |
|------|---------|-------------|
| `DEFAULT_STATE_FIELD` | `"status"` | Field name used as the entity state when none is specified in the lifecycle block |

## Import

```python
from pycharter.domain import (
    get_lifecycle_binding,
    get_domain_entity_info,
    check_state_alignment,
    validate_lifecycle_binding,
    DEFAULT_STATE_FIELD,
)
```

## Lifecycle contract schema

```yaml
# In contract metadata:
metadata:
  lifecycle:
    state_machine_name: order_lifecycle   # required
    machine_version: "1.0.0"              # optional — pin FSM version
    state_field: status                   # optional, default "status"
    entity_id_field: order_id             # optional — field carrying entity ID

# Alternatively under governance_rules:
metadata:
  governance_rules:
    lifecycle:
      state_machine_name: order_lifecycle
```

## Usage examples

### Reading a lifecycle binding

```python
from pycharter.domain import get_lifecycle_binding

meta = {
    "governance_rules": {
        "lifecycle": {
            "state_machine_name": "order_lifecycle",
            "machine_version": "2.0.0",
            "state_field": "order_status",
            "entity_id_field": "order_id",
        }
    }
}

binding = get_lifecycle_binding(meta)
# {'state_machine_name': 'order_lifecycle', 'machine_version': '2.0.0', ...}
```

### Getting domain entity info from a full contract

```python
from pycharter import build_contract
from pycharter.domain import get_domain_entity_info

contract = build_contract("orders", "1.0.0", store)
info = get_domain_entity_info(contract)

if info:
    machine = info["state_machine_name"]
    state_field = info["state_field"]
    entity_id_field = info.get("entity_id_field", "id")
    print(f"FSM: {machine}, state field: {state_field}")
```

### Checking alignment between contract and FSM states

```python
from pycharter.domain import check_state_alignment

result = check_state_alignment(
    contract_dict=contract,
    fsm_state_names=["NEW", "PROCESSING", "SHIPPED", "DELIVERED", "CANCELLED"],
    state_field="order_status",
)

if not result["aligned"]:
    if result["missing_from_contract"]:
        print(f"Add to contract enum: {result['missing_from_contract']}")
    if result["missing_from_fsm"]:
        print(f"Add to FSM: {result['missing_from_fsm']}")
```

### Validating a lifecycle binding block

```python
from pycharter.domain import validate_lifecycle_binding

errors = validate_lifecycle_binding(meta)
if errors:
    for err in errors:
        print(f"  ✗ {err}")
```

## See also

- [Domain Models and Lifecycle guide](../guides/domain-models-and-lifecycle.md)
- [Contract Parser](contract-parser.md)
