diff --git a/CLAUDE.md b/CLAUDE.md index 3088fbc..cce4b9f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -92,8 +92,14 @@ will not run under Ray.Di or will break framework expectations. 7. **Semantic validators**: one class per concept, one `#[Validate]` method, throw a domain exception from `src/Exception/`. Link to schema.org in the docblock when a standard term exists (`@link https://schema.org/…`). -8. **Reason services**: always define an `…Interface` and depend on the - interface, never the concrete class. Ray.Di binds the implementation. +8. **Reason services**: Reasons sitting at an **external I/O boundary** + (HTTP, DB, payment gateway, third-party API, filesystem, clock, randomness) + MUST define an `…Interface`; consumers depend on the interface and Ray.Di + binds the implementation — so tests can swap in a Fake. Reasons that are + **pure in-process policies or calculators** (rule-book classes with no + I/O) MAY be injected as concrete classes; no interface is required. + Examples: `PaymentGatewayInterface` and `CreditBureauInterface` (boundary); + `IncomePolicy` and `JTASProtocol` (pure policy). 9. **Namespaces**: follow the existing per-demo pattern (`Be\Pattern\\\…` or `Be\App\\…`). Never invent a new root namespace.