|
| 1 | +# Override Rules |
| 2 | + |
| 3 | +The `MaatifyException` base class allows developers to override default metadata (HTTP Status, Error Code) but enforces strict guardrails. |
| 4 | + |
| 5 | +## 1. Category Immutability |
| 6 | + |
| 7 | +You **cannot** override the category of an exception. |
| 8 | + |
| 9 | +* `ValidationMaatifyException` will always be `VALIDATION`. |
| 10 | +* `SystemMaatifyException` will always be `SYSTEM`. |
| 11 | + |
| 12 | +This prevents "Taxonomy Drift" where exceptions lose their semantic meaning. |
| 13 | + |
| 14 | +## 2. Error Code Constraints |
| 15 | + |
| 16 | +If you provide an `$errorCodeOverride` in the constructor: |
| 17 | + |
| 18 | +1. The code **must exist** in the `ALLOWED_ERROR_CODES` mapping for that category. |
| 19 | +2. If it does not match, a `LogicException` is thrown immediately. |
| 20 | + |
| 21 | +### Fallback Semantics |
| 22 | + |
| 23 | +The default policy validation is permissive for unconfigured categories: |
| 24 | + |
| 25 | +* **Unconfigured category:** Allows **all** codes. |
| 26 | +* **Configured category with empty list:** Allows **all** codes. |
| 27 | +* **Configured category with codes:** Strictly enforces the allowed list. |
| 28 | + |
| 29 | +**Example:** |
| 30 | +* `ValidationMaatifyException` allows `INVALID_ARGUMENT`. |
| 31 | +* It forbids `DATABASE_CONNECTION_FAILED`. |
| 32 | + |
| 33 | +*(Note: Since `ValidationMaatifyException` is abstract, these rules apply to any concrete class extending it.)* |
| 34 | + |
| 35 | +## 3. HTTP Status Class Guard |
| 36 | + |
| 37 | +If you provide an `$httpStatusOverride`: |
| 38 | + |
| 39 | +1. It **must match the default status class** (Client Error vs Server Error). |
| 40 | +2. `4xx` defaults can be overridden with other `4xx` codes. |
| 41 | +3. `5xx` defaults can be overridden with other `5xx` codes. |
| 42 | +4. **Cross-class overrides are forbidden.** (e.g., 400 -> 500). |
| 43 | + |
| 44 | +This ensures that a client-side error (Validation) never accidentally reports a server-side failure (System) to monitoring tools. |
| 45 | + |
| 46 | +## 4. Policy Customization |
| 47 | + |
| 48 | +You can inject a custom `ErrorPolicyInterface` to override default rules (e.g., allow extra codes). |
| 49 | + |
| 50 | +```php |
| 51 | +// Create a policy with custom rules |
| 52 | +$customPolicy = DefaultErrorPolicy::withOverrides( |
| 53 | + allowedOverrides: ['VALIDATION' => ['MY_CUSTOM_CODE']] |
| 54 | +); |
| 55 | + |
| 56 | +// Inject globally (PROCESS-WIDE) |
| 57 | +MaatifyException::setGlobalPolicy($customPolicy); |
| 58 | +MaatifyException::setGlobalEscalationPolicy($customEscalationPolicy); |
| 59 | +``` |
| 60 | + |
| 61 | +### Resolution Precedence |
| 62 | + |
| 63 | +The library resolves policies in the following order: |
| 64 | + |
| 65 | +1. **Escalated:** (Highest Priority) Logic derived from previous exception wrapping. |
| 66 | +2. **Override:** Instance-specific overrides passed to the constructor. |
| 67 | +3. **Default:** The active `ErrorPolicyInterface` (Global or Default). |
| 68 | + |
| 69 | +### ⚠️ Warning: Long-Running Processes |
| 70 | + |
| 71 | +In persistent environments (e.g., **Swoole**, **RoadRunner**), static global state persists across requests. Global policy setters (`setGlobalPolicy`, `setGlobalEscalationPolicy`) are **PROCESS-WIDE**. |
| 72 | + |
| 73 | +* **Risk:** Setting a global policy in one request may affect subsequent requests. |
| 74 | +* **Best Practice:** Set global policies only during application bootstrap, before handling any requests. |
| 75 | +* **Cleanup:** Use `MaatifyException::resetGlobalPolicies()` to clear all static overrides. |
0 commit comments