diff --git a/psalm.xml b/psalm.xml
index 41ebf74..72b23f2 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -26,6 +26,8 @@
+
+
diff --git a/tests/stubs/oc_core_controller_clientflowloginv2controller.php b/tests/stubs/oc_core_controller_clientflowloginv2controller.php
new file mode 100644
index 0000000..d8de80f
--- /dev/null
+++ b/tests/stubs/oc_core_controller_clientflowloginv2controller.php
@@ -0,0 +1,128 @@
+|JSONResponse, array{}>
+ *
+ * 200: Login flow credentials returned
+ * 404: Login flow not found or completed
+ */
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[FrontpageRoute(verb: 'POST', url: '/login/v2/poll')]
+ #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
+ public function poll(string $token): JSONResponse
+ {
+ }
+
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
+ #[UseSession]
+ #[FrontpageRoute(verb: 'GET', url: '/login/v2/flow/{token}')]
+ public function landing(string $token, $user = '', int $direct = 0): Response
+ {
+ }
+
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
+ #[UseSession]
+ #[FrontpageRoute(verb: 'GET', url: '/login/v2/flow')]
+ public function showAuthPickerPage(string $user = '', int $direct = 0): StandaloneTemplateResponse
+ {
+ }
+
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
+ #[UseSession]
+ #[FrontpageRoute(verb: 'GET', url: '/login/v2/grant')]
+ #[NoSameSiteCookieRequired]
+ public function grantPage(?string $stateToken, int $direct = 0): StandaloneTemplateResponse
+ {
+ }
+
+ #[PublicPage]
+ #[FrontpageRoute(verb: 'POST', url: '/login/v2/apptoken')]
+ public function apptokenRedirect(?string $stateToken, string $user, string $password)
+ {
+ }
+
+ #[NoAdminRequired]
+ #[UseSession]
+ #[PasswordConfirmationRequired(strict: false)]
+ #[FrontpageRoute(verb: 'POST', url: '/login/v2/grant')]
+ public function generateAppPassword(?string $stateToken): Response
+ {
+ }
+
+ /**
+ * Init a login flow
+ *
+ * @return JSONResponse
+ *
+ * 200: Login flow init returned
+ */
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[FrontpageRoute(verb: 'POST', url: '/login/v2')]
+ #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)]
+ public function init(): JSONResponse
+ {
+ }
+}
diff --git a/tests/stubs/oc_core_service_loginflowv2service.php b/tests/stubs/oc_core_service_loginflowv2service.php
new file mode 100644
index 0000000..330da2a
--- /dev/null
+++ b/tests/stubs/oc_core_service_loginflowv2service.php
@@ -0,0 +1,86 @@
+