Revision history for PAGI::FastAPI

1.0.0  2026-08-12
       [FEATURE]
       - Refactored core framework to modern Perl syntax: use experimental 'class'.
       - Added PAGI::FastAPI::RateLimit::Driver abstract async base class
         for pluggable rate-limiting storage drivers.
       - Added PAGI::FastAPI::RateLimit::Driver::Memory as the built-in,
          default in-memory storage driver.
       - Added PAGI::FastAPI::Middleware::RateLimit to support app-level
         and route-level rate limiting using a fixed time-window counter.
       - Added PAGI::FastAPI::BotProtection::ProofOfWork for stateless
         cryptographic bot mitigation.
       - Added PAGI::FastAPI::Middleware::BotProtection middleware to
         automatically enforce challenge/response flow on unauthenticated
         requests.
       - Added $app->add_bot_protection() helper method to PAGI::FastAPI.
       - Added PAGI::FastAPI::Response::SSE to support production-grade
         Server-Sent Events (SSE) streaming via PAGI::SSE.
       - Added $c->sse() context helper method for simplified SSE stream
         creation with support for keepalives, custom headers, and auto-JSON
         serialisation.
       - Added $c->sse() helper method to PAGI::FastAPI::Context for
         Server-Sent Events support.
       - Added $c->sleep() non-blocking sleep utility method using Future::IO.
       - Added PAGI::FastAPI::Response base class to standardise HTTP
         response handling across HTML, SSE, and JSON handlers.
       - Improved route response dispatcher in PAGI::FastAPI to correctly
         route streaming responses (can('dispatch')) and response objects
         without triggering JSON serialization errors.
       - Added stringification overload fallback for response classes.
       - Added enable_csrf(), to_pagi() to PAGI::FastAPI.
       - Added csrf_token(), csrf_verify(), pagi_context() to PAGI::FastAPI::Context.

       [DOCUMENTATION]
       - Updated POD for core classes and added comprehensive POD for:
         PAGI::FastAPI::RateLimit::Driver,
         PAGI::FastAPI::RateLimit::Driver::Memory,
         PAGI::FastAPI::Middleware::RateLimit,
         PAGI::FastAPI::BotProtection,
         PAGI::FastAPI::BotProtection::ProofOfWork,
         PAGI::FastAPI::Middleware::BotProtection,
         PAGI::FastAPI::Response,
         PAGI::FastAPI::Response::HTML and
         PAGI::FastAPI::Response::SSE.

       [TESTS]
       - Added integration tests for rate limiting: t/12-rate_limit.t.
       - Added comprehensive unit test suite: t/13-bot_protection.t.
       - Added test suite for PAGI::SSE: t/14-sse_streaming.t
       - Added test for HTML response: t/15-html_response.t
       - Added test for CSRF: t/16-middleware_csrf.
       - Added t/17-enable_csrf_app_secret.t covering the app-level secret
         fallback fix, the call-level override, and the "no secret
         anywhere" error path.
       - Added t/18-context_extras.t covering PAGI::FastAPI::Context's
         param(), csrf_token(), csrf_verify(), html(), sse(), and sleep(),
         none of which had any prior test coverage.
       - Added t/19-ratelimit_driver_memory.t: direct unit tests for
         PAGI::FastAPI::RateLimit::Driver::Memory, including a regression
         test for the increment_async() two-value contract.
       - Added t/20-bot_protection_ipv6.t: regression tests for the IPv6
         delimiter fix and the difficulty=0 edge case.
       - Added t/21-depends.t covering PAGI::FastAPI::Depends, including
         the previously-untested ADJUST non-CODE-reference guard.

       [EXAMPLES]
       - Added working example of SSE: eg/sse_demo.pl
       - Added working example of CSRF: eg/csrf_demo.pl

       [PACKAGING]
       - Corrected MIN_PERL_VERSION in Makefile.PL from 5.036 to 5.038000.
         The `class`/`field`/`method`/`ADJUST` keywords used throughout lib/
         (via `use experimental 'class'`) were only added to the Perl
         interpreter in 5.38.0; they do not exist in 5.36, regardless of
         the `use experimental` pragma. Every lib/*.pm now consistently
         declares `use v5.38;` to match.
       - Added TEST_REQUIRES entries: Test::Fatal and PAGI::Test::Client,
         both of which the test suite already depended on without declaring.

0.1.0  2026-08-10
       [BREAKING]
       - The add_cors function now utilizes PAGI::Middleware::CORS instead
         of implementing its own version, based on the recommendation of the
         author of the PAGI specifications. The reason to make this switch
         is the established use of PAGI::Tools in other components of the
         package. The previous names of the options have been changed, as
         follows: allow_origins and allow_methods were replaced with origins
         and methods, respectively, while the new default value for max_age
         changed from 600 to 86,400. The value of max_age is the default one
         used by PAGI::Middleware::CORS. There is also a new value called
         expose_headers.
       - CORS is added as the outermost level in to_app() and will be
         applied after mount()-ed sub-applications and static files are
         created. Thus, CORS will be applied throughout the application and
         not only to get/post/other functions like before.
       - New requirement: PAGI::Middleware::CORS >= 0.002002 (comes with the
         same PAGI::Tools package as PAGI::WebSocket, already in the list of
         prerequisites. Also, presented here explicitly as being directly
         utilised).

       [DOCUMENTATION]
       - The previous event-loop section has been revised (renamed from
         "MIXING WITH OTHER EVENT LOOPS" to "EVENT LOOPS: FUTURE::IO IS THE
         GOAL, IO::ASYNC IS AN IMPLEMENTATION DETAIL"), at the request of
         the author of the PAGI specification: previously, it stated that
         "PAGI::FastAPI works entirely on IO::Async," although this makes it
         sound like a load-bearing requirement instead of simply an
         implementation detail. It now insists on Future::IO being the
         recommended way of writing your own event-driven code (timers,
         delays) and provides a working example following the heartbeat
         pattern presented in the chat-server example. The
         IO::Async::Loop::EV/IO_ASYNC_LOOP=EV technology has been preserved,
         but it is defined as simply a backup solution used in very specific
         cases involving the use of Mojo::IOLoop-based libraries that
         appeared prior to Future::IO.

0.0.9  2026-08-08
       [BREAKING]
       - Removed PAGI::FastAPI::WebSocket entirely.
       - websocket() handlers now receive a plain PAGI::WebSocket instance
         directly. For anyone who wasn't relying on the class name itself
         (isa checks, `use PAGI::FastAPI::WebSocket` directly), this is a
         no-op - every method, return type, and calling convention is
         unchanged from 0.0.10, since that version was already a strict,
         override-free subclass.
       - _handle_websocket now sets $scope->{path_params} directly and
         calls PAGI::WebSocket->new($scope, $receive, $send) - the same
         glue that used to live in the now-removed class's constructor.
       - Dropped the now-unused JSON::MaybeXS prereq (it was only ever
         needed by the removed class) and the PAGI::FastAPI::WebSocket
         entry from t/00-load.t and the provides map.

0.0.8  2026-08-08
       [DOCUMENTATION]
       - There is a new "MIXING WITH OTHER EVENT LOOPS" section which
         describes the interoperability issue between IO::Async (on which
         PAGI::FastAPI is based) and Mojo::IOLoop-based libraries like
         Mojo::Pg. The paragraph in question explains that IO::Async allows
         calls to the non-blocking API to hang unless both libraries utilise
         the same reactor. The other method of calling a library in a
         blocking manner locks every other connection in the process. The
         solution is detailed (IO::Async::Loop::EV + IO_ASYNC_LOOP=EV,
         along with wrapping the callback API in a Future).

0.0.7  2026-08-08
       [DOCUMENTATION]
       - Reworded PAGI::FastAPI::WebSocket's receive_text()/receive_bytes()
         POD, which previously said they "block asynchronously" - a
         self-contradictory phrase that read as "this blocks the server" to
         at least one reader. Now states plainly that they suspend only the
         current connection's coroutine and never block the event loop or
         other connections. Added the same clarification to the module
         DESCRIPTION. No code changes; the implementation was already
         correctly non-blocking (verified against PAGI::Server::Connection's
         per-connection dispatch, which detaches each handler via
         adopt_future rather than awaiting it inline).

0.0.6  2026-08-08
       [ENHANCEMENTS]
       - Full support for WebSocket routing has been added and is available
         by creating a $app->websocket() endpoint. The implementation is
         completed with async frame handling and parameter extraction
         capabilities.
       - A new class called PAGI::FastAPI::WebSocket has been introduced. It
         allows for the non-blocking implementation of the handshake and
         message methods: accept(), close(), receive_text(), receive_json(),
         receive_bytes(), send_text(), send_json(), send_bytes().
       - The mount() method has been implemented, allowing PAGI
         sub-applications, static files, and routers to be mounted via
         PAGI::App::URLMap.
       - The add_middleware() method has been implemented for registering
         custom async middleware.
       - The WebSocket routes were excluded from the generated OpenAPI
         documentation version 3.1.

       [BUG FIXES & ERROR HANDLING]
       - The unmatched WebSocket routes already reject the connections with
         a close code 4004 before the acceptance of handshake.
       - Unhandled exceptions in the WebSocket handlers lead to open
         connections termination with a close code 1011 automatically.
       - Dialing execution errors on the WebSocket endpoints lead to the
         closure of the connections automatically with the status code 1008.

       [DOCUMENTATION & EXAMPLE]
       - Chat server application was added to showcase HTML/JavaScript
         and WebSocket functionality.
       - Updated module documentation and SYNOPSIS for PAGI::FastAPI and
         PAGI::FastAPI::WebSocket.

       [TESTING]
       - Created t/11-websocket.t that includes handshakes, echo flows,
         path parameters, JSON payload handling and status codes of close.
       - Updated t/00-load.t to incorporate PAGI::FastAPI::WebSocket.

0.0.5  2026-08-06
       [ENHANCEMENT]
       - The POST/PUT/PATCH request bodies can now be in the application/x-www-form-urlencoded
         format instead of being restricted to JSON. The body parser examines
         the Content-Type header; therefore, the charset suffix (such as ";charset=utf-8")
         will be ignored.
         Furthermore, the body parser will process url-encoded data in the
         same manner as query string in which the body is decoded using
         percent-/plus-decode algorithm. However, the same Type::Tiny
         validation can be applied in either format and the handler will
         receive a HashRef object as a result of a processed request
         regardless of the sent format.
       - It is backward compatible, i.e., if the Content-Type header is not
         set or not recognised, the body will be processed in the same way
         as before. In particular, the default behavior of parsing requests
         is JSON parsing.
       - Also the new feature was tested in t/10-form_urlencoded_body.t.
       - The plugin is documented in the `body` configuration option as well
         as in the ERROR HANDLING section. The decision to implement this
         feature was influenced by the example provided on a
         PAGI::FastAPI::Security page.

0.0.4  2026-08-05
       [DOCUMENTATION]
       - Included an AUTHENTICATION AND SECURITY part in the POD to highlight
         the dependencies and components of middleware and provided information
         about the new companion distribution called PAGI::FastAPI::Security
         for the ready-to-use schemes related to HTTP Bearer, HTTP Basic,
         API Key, and OAuth2 password-bearer.
       - Added a Pluggable Authentication item in Key Features List.
       - Added PAGI::FastAPI::Security and DBIx::Class::Async to SEE ALSO section.
       - Mentioned in the SYNOPSIS the introduction about the functionality
         of hand-rolled Bearer-token checks in this context and referring to
         PAGI::FastAPI::Security for production use.
       - Added a similar entry in README.md as well.
       [EXAMPLE]
       - Updated the example to demo authentication using PAGI::FastAPI::Security:
         eg/dbic_async_integration.pl

0.0.3  2026-08-04
       [EXAMPLE]
       - Added integration demo script:
         eg/integration_demo.pl

0.0.2  2026-08-04
       [BUGFIX]
       - Routes no longer consider metacharacters in their static paths
         (like ".", "+", "?") as wildcards. Only placeholders {param}
         are transformed into capture groups. Previously, it would allow
         the route '/items.json/{id}' to match paths like '/itemsXjson/{id}'.
       - The values of path parameters and query string parameters are now
         appropriately decoded: '%XX' and '+' decoding is now done as it
         should be according to the application/x-www-form-urlencoded rules.
         Until now strings like 'John%20Doe' were sent to handlers unchanged.
       - The request body reader no longer goes into an infinite loop when
         the PAGI server sends a non-'http.request' event (for example
         'http.disconnect') while transmitting POST/PUT/PATCH requests.
       - When registering routes, the process now fails with a clear message
         instead of just ignoring misconfiguration. For instance, absence
         of a 'handler' property, 'dependencies' property not being a HashRef
         or an ArrayRef is rejected immediately during route registration.
       [TESTING]
       - A new test was added in t/08-input_handling_and_registration.t
         covering the above-mentioned aspects.
       - A new test was added in t/09-external_async_resource_integration.t
         to cover DBIx::Class::Async integration.
       [EXAMPLE]
       - Added additional DBIx::Class::Async integrated application:
         eg/dbic_async_integration.pl

0.0.1  2026-08-03
       - Initial CPAN release.
       - Asynchronous routing engine built on top of PAGI ($scope, $receive, $send).
       - Type-safe parameter & POST JSON body validation via Type::Tiny.
       - Async Middleware pipeline support with built-in CORS helper (add_cors).
       - FastAPI-style Dependency Injection system via PAGI::FastAPI::Depends.
       - Integrated OpenAPI 3.1 schema (/openapi.json) and interactive Swagger UI (/docs).
