SECURITY FEATURE
Session Payloads
Session state should be explicit, typed, and reviewable — not a bag of magic keys spread across handlers.
Feature Guide
A quick orientation block that answers the essential questions: what this feature does, how it works, why it matters, and the key concepts behind it.
What this does
Semitexa treats session state as a typed contract. We do not allow auth state to spread through $this->session->get('current_user') and other string-key guesses.
How it works
A dedicated class marked with #[SessionSegment] owns the session shape. Handlers read and write that payload through SessionInterface::getPayload() and SessionInterface::setPayload(), while semantic methods such as requireUserId() or clear() live on the payload itself.
Why it matters
This kills one of the most persistent sources of auth drift in PHP apps: invisible session conventions. The contract becomes explicit, reviewable, and refactor-safe instead of hiding behind magic key names and duplicated null checks.
Key concepts
- #[SessionSegment]
- Declares a typed session payload and binds it to one named session segment.
- Session Payload
- The explicit DTO-like class that owns one session concern instead of scattering string keys across handlers.
- SessionInterface::getPayload()
- Typed session access API that hydrates the declared payload instead of returning loose values by string key.
- string-key session chaos
- The legacy pattern where session contracts exist only as ad hoc names like current_user, auth_user, or user_id.
Session Contract
We ended string-key session chaos
Semitexa does not treat session state as a random key-value bag. If some state matters, it must live in a dedicated Session Payload with a typed shape and meaningful methods.
What usually goes wrong
- String keys like current_user, auth_user, or user_id drift across handlers, middleware, and listeners until nobody knows the real contract anymore.
- Every caller starts duplicating has/get/null checks because the session shape is implicit and fragile.
- Renaming one key becomes a distributed grep problem instead of a refactor-safe code change.
Session reads happen through ad hoc strings, so every caller has to remember both the key names and the failure cases.
The real auth contract lives in tribal knowledge, not in code.
A dedicated Session Payload owns the shape, and handlers ask for that payload directly through SessionInterface.
Reviewers can see the contract immediately, and refactors stay local.
Semitexa rule
- Session state belongs to a dedicated payload class marked with #[SessionSegment].
- Code reads session state through SessionInterface::getPayload(), not arbitrary string keys.
- Meaningful methods such as requireUserId() or clear() belong on the payload itself.
- If no Session Payload exists for a concern, that concern should not be writing random session keys.
Verified against Semitexa Ultimate 2026.09.19.1020
Session Payloads
Semitexa treats session state as a typed contract, not as an unstructured key-value dump.
How it works
Every piece of session state belongs to a dedicated class marked with #[SessionSegment]. Handlers read and write session state through SessionInterface::getPayload() and SessionInterface::setPayload(). Arbitrary string key access is not available — if no Session Payload exists for a concern, that concern should not be writing to the session.
Why this matters
String-key sessions rot. Keys drift across handlers, middleware, and listeners until nobody knows the real contract. Renaming one key becomes a distributed grep problem. Typed Session Payloads make the contract reviewable, refactor-safe, and local to a single class.
How it works
A dedicated class marked with #[SessionSegment] owns the session shape. Handlers read and write that payload through SessionInterface::getPayload() and SessionInterface::setPayload(), while semantic methods such as requireUserId() or clear() live on the payload itself.
Why it matters
This kills one of the most persistent sources of auth drift in PHP apps: invisible session conventions. The contract becomes explicit, reviewable, and refactor-safe instead of hiding behind magic key names and duplicated null checks.
Key concepts
- #[SessionSegment]
- Declares a typed session payload and binds it to one named session segment.
- Session Payload
- The explicit DTO-like class that owns one session concern instead of scattering string keys across handlers.
- SessionInterface::getPayload()
- Typed session access API that hydrates the declared payload instead of returning loose values by string key.
- string-key session chaos
- The legacy pattern where session contracts exist only as ad hoc names like current_user, auth_user, or user_id.