ADR 015 · Accepted
Type-Safe Domain Models via PHP 8.1+ Enums & Value Objects
Context
Domain constants were stringly-typed throughout the codebase. Adapter types were plain strings ('openai', 'anthropic'), capabilities were CSV strings in database columns, task categories and output formats were validated ad-hoc. This caused subtle bugs and PHPStan violations at higher analysis levels.
Problem statement
No compile-time safety: Typos like 'opanai' pass silently at runtime.
Scattered validation: Each usage site re-validated allowed values.
Missing behavior: Constants carried no associated logic (labels, icons, defaults).
PHPStan violations: Stringly-typed comparisons defeated type narrowing.
Decision
Use PHP 8.1+ backed enums for all domain constants. Each enum provides:
A string-backed value for database/API compatibility.
Static helpers: values(), isValid(), tryFromString().
Domain-specific methods: label(), getIconIdentifier(), getContentType().
Enums implemented:
Enum |
Purpose |
Cases |
|---|---|---|
AdapterType |
LLM provider protocol type |
9 cases (OpenAI through Custom) |
ModelCapability |
Model feature flags |
11 cases (chat, completion, embeddings, vision, streaming, tools, json_mode, audio, image, text_to_speech, transcription) |
TaskCategory |
Task organization |
5 cases (content, log_analysis...) |
TaskInputType |
Task input source |
5 cases (manual, syslog, file...) |
TaskOutputFormat |
Response rendering format |
4 cases (markdown, json...) |
ModelSelectionMode |
Model selection strategy |
2 cases (fixed, criteria) |
Immutable readonly DTOs for composite data transfer:
DetectedProvider -- Provider detection result with confidence score.
DiscoveredModel -- Model metadata from API discovery.
SuggestedConfiguration -- AI-generated configuration preset.
CompletionResponse -- Immutable final readonly class for LLM responses.
Consequences
Positive:
●● Invalid values caught at instantiation (BackedEnum::from() throws).
●● PHPStan level 10 compliance without @phpstan-ignore suppressions.
● Self-documenting: AdapterType::OpenAI->defaultEndpoint() vs string lookup.
● IDE auto-completion and refactoring support.
◐ match expressions enforce exhaustive handling of all cases.
Negative:
◑ Requires PHP 8.1+ (already the minimum for TYPO3 v13).
◑ Enum #[CoversNothing] needed for PHPUnit 12 coverage.
Net Score: +6.0 (Strong positive)
Files changed
Added:
Classes/Domain/Model/AdapterType.php
Classes/Domain/Enum/ModelCapability.php
Classes/Domain/Enum/ModelSelectionMode.php
Classes/Domain/Enum/TaskCategory.php
Classes/Domain/Enum/TaskInputType.php
Classes/Domain/Enum/TaskOutputFormat.php
Modified:
Classes/Domain/Model/Provider.php -- Uses AdapterType enum.
Classes/Domain/Model/Model.php -- Uses ModelCapability enum.
Classes/Domain/Model/Task.php -- Uses TaskCategory, TaskInputType, TaskOutputFormat.
Classes/Provider/AbstractProvider.php -- Adapter type matching via enum.