# Core Boundaries (MUST / MUST NOT)

## Schichtgrenzen

1. MUST SQL nur in `lib/Repository/**` halten.
2. MUST Business-Logik in `lib/Service/**` halten.
3. MUST `pages/**` auf Input, Auth/AuthZ, Orchestrierung, Response begrenzen.
4. MUST NOT Business- oder Permission-Logik in `templates/**` legen.

## Instanziierung

1. MUST in Actions/Helpern/Templates nur `app(Foo::class)` verwenden.
2. MUST NOT in `pages/**` direkt `new ...Service|Gateway|Repository` nutzen.
3. MUST NOT in `lib/Service/**` (ausser `*Factory.php`) direkt `new ...Factory|Service|Gateway|Repository` nutzen.
4. MUST NOT in `pages/admin/**` `Factory::class` referenzieren oder `app(...Factory::class)->create...` nutzen.

## Input / Validation

1. MUST Input in `pages/**` ueber `requestInput()` lesen.
2. MUST NOT `$_POST`, `$_GET`, `$_FILES`, `REQUEST_METHOD` in `pages/**` verwenden.
3. MUST NOT `$_SESSION`, `$_SERVER`, `$_COOKIE`, `$_ENV` in `pages/**` direkt verwenden.
4. MUST Form-Validation ueber `FormErrors` fuehren.
5. MUST API-Validation-Fehler ueber `ApiResponse::validationFromFormErrors(...)` ausgeben.
6. MUST NOT `ApiResponse::readJsonBody(...)` in `pages/api/v1/**` verwenden.

## List-Data Endpoints

1. MUST `pages/**/data().php` als GET-only Endpunkte umsetzen (`gridRequireGetRequest()`).
2. MUST Query-Filter ueber `gridParseFilters(...)` + `filter-schema.php` normalisieren.
3. MUST NOT Query-Filter inline/parallele Alias-Parser in `data().php` neu einfuehren.

## Security / API

1. MUST AuthZ serverseitig erzwingen.
2. MUST Tenant-Scope serverseitig erzwingen.
3. MUST CSRF auf POST-Endpunkten vor Body-Verarbeitung verifizieren.
4. MUST NOT PII/Secrets unredacted in Logs oder Audit-Metadata schreiben.
5. MUST SQL nur ueber Repository mit prepared statements ausfuehren.
6. MUST extern UUID-first bleiben.
7. MUST API-Fehler konsistent halten (`error`, optional `errors`).
8. MUST OpenAPI im selben Merge aktualisieren, wenn API geaendert wird.

## Pruef-Hinweis

- Harte Repo-Gates: `tests/Architecture/CoreStarterkitContractTest.php`
