Clean Framework · DOCUMENTATION
Behavioral API guide
Behavioral API guide
Bounded candidate reference — 2026-10-20: 0.2.0-rc.1 is committed locally through 84f415b3098af5653577b2c65eea31fca21df79c, unpublished and not production-approved; stable PHP >=8.5.11 <8.6.0 is required. This is documentation, not adoption: this knowledge base retains its installed 0.1.0-rc.1 dependency and PHP 8.2.11 local profile. Dated PHP 8.2 evidence is historical; earlier dirty-source reports retain their original test provenance, not retroactive clean-commit proof. Candidate examples are illustrative: API signatures were reviewed, but candidate code was not executed by this editorial update. See current checkpoint, open criteria and adoption boundary.
Candidate API changes include per-claim queue/outbox authority, stricter logging and contextual encoders. See compatibility and maintenance; do not use an old process label as a lease token.
This is a curated navigation and contract guide, not an exhaustive generated class reference. Public signatures and docblocks in the linked source files are authoritative for the installed framework version. Collection annotations describe shapes; prose explains ownership, side effects, and failure behavior.
Core contracts and where to start
| Boundary | Public API and semantics | Detailed guide |
|---|---|---|
| Configuration | Loader loads file paths, selects an explicit environment, converts bindings, validates schema, and returns immutable Config. secret() requires an available SecretValue; missing() reports names, not values. | Configuration |
| Dependency injection | Container supports transient, singleton, and scoped bindings. Freeze registration before handling work; scoped resolution requires an active scope. | Container |
| HTTP input | Request normalizes methods/headers and enforces body/upload bounds. Input remains untrusted; framework.* and app.* attributes are separate namespaces. | HTTP |
| HTTP output | Response constructs output without sending it. json() returns a safe 500 response on encoding failure; file() enforces a supplied root and defers streaming; send once at the front controller. | HTTP |
| Routing | Router resolves registered handlers after route middleware; constraints validate path shape, not domain access. | Routing |
| PHP views | ViewFactory merges shared, local, and composer data; Renderer contains PHP files and cleans output buffers on exceptions. Templates are trusted code, not a sandbox for uploads. | Views |
| SQL | SqlIdentifier selects MySQL-style identifiers from a closed application map. Bind SQL values through a Connection, never through identifier concatenation. | Database |
| Migrations | MigrationDiscovery requires trusted PHP migration files, checks IDs/checksums, sorts by ID, and caches discovery for that instance. It is not a data-only file parser. | Migrations |
| Console | Application accepts argv-style arguments, checks policy, releases locks, and maps failures to safe exit codes. CommandInputParser rejects undeclared or repeated options. | Operations |
| Identity and private delivery | SessionManager lazily enforces policy; authentication places identity under RequestAttribute::PRINCIPAL. ProtectedFileService authorizes before resolving private storage. | Security |
| Jobs and schedules | QueueWorker handles bounded leased attempts and reports retry/unknown outcomes; ScheduleRunner checks feature/overlap policy and records history. Durable concurrency depends on the supplied stores. | Queue and scheduler |
| Provider transport | HttpRequest validates bounded request policy without making a call; HttpResponse validates response metadata and classifies malformed JSON. | Providers |
| OAuth | OAuthFlow binds state/PKCE to exact provider and environment; completion requires browser-owned expected state and single-use storage. | OAuth |
| Revisions | RevisionManager appends at an expected version; restoring adds a new revision, never changes old history. The caller owns authorization and domain transactions. | Revisions |
| Structured AI | AiGenerationRequest carries untrusted data, version references, and budgets. StructuredAiBroker independently checks schema/budgets; proposals do not execute actions. | AI and Assisted Actions |
Example: choose an identifier without interpolating input
use Clean\Framework\Database\SqlIdentifier;
// Application policy supplies this closed map; never populate it from a request.
$column = SqlIdentifier::fromAllowlist('newest', [
'newest' => 'created_at',
'alphabetical' => 'title',
]);
// $column is the quoted identifier `created_at`; unknown choices throw.
// Ordinary WHERE values still use the connection's bound parameters.Example: understand returned responses and missing configuration
use Clean\Framework\Config\Config;
use Clean\Framework\Http\Response;
// Hand-created test configuration is not a substitute for Loader/schema in production.
$config = new Config(['environment' => 'test', 'app' => ['name' => 'Demo']]);
$missingKeys = $config->missing(['app.name', 'provider.token']);
// Reports only ['provider.token']; it does not reveal a value or contact a provider.
$response = Response::json(['success' => true, 'data' => ['name' => $config->require('app.name')]]);
// Return $response from the controller. The front controller sends it once.For a complete assembled example rather than isolated fragments, follow APPLICATION_WALKTHROUGH.md.
Writing and reviewing API comments
For non-trivial APIs, document the operation before annotations, then address these questions where applicable:
- What does the caller supply, and which values must be trusted?
- What is returned on missing/denied/unsupported input?
- Which validation, typed exceptions, or safe failure responses can occur?
- Does the method perform I/O, invoke callbacks, cache data, or mutate state?
- Who owns transactions, authorization, cleanup, retries, and idempotency?
- Is the lifetime local, single-host, or dependent on an atomic shared adapter?
Keep comments faithful to the actual implementation. For example, a deadline checked after a callback returns is not preemptive termination, and a local lease adapter is not a distributed guarantee. Short shape annotations on a simple collection accessor need not become paragraphs of repeated syntax.
Automated checks and their limits
composer verify requires public method docblocks throughout the neutral framework and portability application. php bin/documentation-check also checks relative Markdown file links and behavioral summaries on a reviewed set of non-trivial APIs. Root tests exercise the corrected principal/session examples and detect their known documentation regressions.
These checks cannot prove every explanation is correct, every snippet is a standalone script, or every failure case is documented. The check does not fetch external links or validate Markdown heading fragments. Review prose and examples with code changes; use actual application tests for behavior. Neither check validates the entire byte-preserved legacy bridge against new conventions.
Editorial provenance
Source: docs/API_GUIDE.md. Source SHA-256: f30e5d4a3d27df0f278cb17bf21efa883372b745b5216df85816661a0137751b.
Framework candidate reference; editorial checkpoint 2026-10-20. See candidate status and adoption boundary.