← Routing & Handlers

ROUTING & HANDLERS FEATURE

Public Payload

Anonymous access is never accidental: without #[PublicEndpoint], Semitexa treats the route as protected.

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 is closed by default: every payload requires authentication unless you explicitly opt it into anonymous access with #[PublicEndpoint].

How it works

The access policy resolver inspects payload attributes at boot. If #[PublicEndpoint] is present, the route is marked public; otherwise the authorizer treats guest access as AuthenticationRequired and the pipeline returns 401 before the handler runs.

Why it matters

This flips the usual risk profile. Teams do not have to remember to secure every endpoint one by one. The safe default is built in, and public exposure becomes a deliberate code review event.

Key concepts

#[PublicEndpoint]
Marks a payload as explicitly reachable without authentication.
default private
The absence of #[PublicEndpoint] means the endpoint is treated as protected for guests.
401 Unauthorized
The framework response returned when a guest hits a protected endpoint.
Authorizer
Core service that decides whether the current subject may access the resolved payload.

Security Default

Private unless you say otherwise

The absence of #[PublicEndpoint] is what keeps routes closed to guests. Public access must be deliberate and visible in code.

// Protected by default
#[AsPayload(path: '/dashboard', methods: ['GET'])]
class DashboardPayload {}

// Explicitly public
#[PublicEndpoint]
#[AsPayload(path: '/catalog', methods: ['GET'])]
class CatalogPayload {}
Route declaration Guest request result
No auth attribute at all 401 Unauthorized
#[PublicEndpoint] 200 OK
#[PublicEndpoint] + #[RequiresPermission] Boot-time exception
Authenticated user on default-private route 200 OK
#[AsPublicPayload] #[AsProtectedPayload] #[AsServicePayload] 401 Unauthorized Authorizer

Verified against Semitexa Ultimate 2026.09.19.1020

Public Payload

Semitexa is closed by default. Every payload picks one of three access attributes — #[AsPublicPayload], #[AsProtectedPayload], or #[AsServicePayload] — and the framework refuses to discover a payload that declares none. Anonymous access is the explicit #[AsPublicPayload] opt-in, never an implicit fallback.

How it works

The access policy resolver inspects the payload's access attribute at boot. #[AsPublicPayload] marks the route as anonymous-allowed. #[AsProtectedPayload] requires a User-domain principal and returns 401 to guest requests before the handler runs. #[AsServicePayload] requires a Service-domain principal (a verified webhook signature, machine token, or partner credential) and similarly returns 401 on missing or wrong-domain credentials.

Why this matters

The three attributes are mutually exclusive and explicit. Public exposure becomes a deliberate code-review event because the keyword AsPublicPayload appears at the type. There is no "default protected" fallback that someone could remove; there is no shared base attribute that could accidentally drop a route into the wrong access class. A payload that declares none of the three never reaches the route registry, so a missing attribute is a build-time discovery failure rather than a silently exposed endpoint.

See also

© Jeff Sickel: "Deleted code is debugged code."

Public Payload Trusted input boundary
<?phpdeclare(strict_types=1);namespace App\Payload\Routing;use Semitexa\Core\Attribute\AsPublicPayload;use App\Resource\CatalogPageResource;#[AsPublicPayload(    responseWith: CatalogPageResource::class,    path: '/catalog',    methods: ['GET'],)]final class PublicCatalogPayload{}

How it works

The access policy resolver inspects payload attributes at boot. If #[PublicEndpoint] is present, the route is marked public; otherwise the authorizer treats guest access as AuthenticationRequired and the pipeline returns 401 before the handler runs.

Why it matters

This flips the usual risk profile. Teams do not have to remember to secure every endpoint one by one. The safe default is built in, and public exposure becomes a deliberate code review event.

Key concepts

#[PublicEndpoint]
Marks a payload as explicitly reachable without authentication.
default private
The absence of #[PublicEndpoint] means the endpoint is treated as protected for guests.
401 Unauthorized
The framework response returned when a guest hits a protected endpoint.
Authorizer
Core service that decides whether the current subject may access the resolved payload.

Support Semitexa
Built for developers who prefer control over magic. Your support helps keep it fast, open, and evolving.

Donate via PayPal