diff --git a/.eslintignore b/.eslintignore
index c563964cb..91f29fbc7 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,3 +1,5 @@
 node_modules
 pnpm-lock.yaml
 packages/*/docs
+packages/*/coverage
+
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 02e91f0c7..f06654dc9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -36,6 +36,12 @@ jobs:
       - run: pnpm exec nx-cloud record -- nx format:check --verbose
       - run: pnpm exec nx affected -t build lint test e2e-ci --verbose
 
+      - uses: actions/checkout@main
+      - uses: codecov/codecov-action@v5
+        with:
+          directory: ./packages/*/coverage
+          token: ${{ secrets.CODECOV_TOKEN }}
+
       - uses: actions/upload-artifact@v4
         if: ${{ !cancelled() }}
         with:
diff --git a/.gitignore b/.gitignore
index 712ffee66..a765ab8fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ e2e/token-vault-app/public/assets/
 bundles/
 docs/
 coverage/
+packages/**/coverage/
 node_modules/
 samples/_static/js/*.js*
 tests/**/app/index.js*
diff --git a/e2e/mock-api-v2/.eslintignore b/e2e/mock-api-v2/.eslintignore
index 7787c22e4..1856a2cea 100644
--- a/e2e/mock-api-v2/.eslintignore
+++ b/e2e/mock-api-v2/.eslintignore
@@ -5,4 +5,5 @@ LICENSE
 .env*
 .bin
 dist
-.eslintignore
\ No newline at end of file
+.eslintignore
+coverage
diff --git a/e2e/mock-api-v2/package.json b/e2e/mock-api-v2/package.json
new file mode 100644
index 000000000..0a7acb646
--- /dev/null
+++ b/e2e/mock-api-v2/package.json
@@ -0,0 +1,13 @@
+{
+  "name": "mock-api",
+  "version": "0.0.0",
+  "private": true,
+  "description": "",
+  "main": "./dist/index.js",
+  "module": "./dist/index.js",
+  "exports": "./dist/index.js",
+  "keywords": [],
+  "author": "",
+  "type": "module",
+  "license": "ISC"
+}
diff --git a/e2e/mock-api-v2/project.json b/e2e/mock-api-v2/project.json
index f7210829e..300b79fa7 100644
--- a/e2e/mock-api-v2/project.json
+++ b/e2e/mock-api-v2/project.json
@@ -69,9 +69,6 @@
         "{projectRoot}/{options.coverage.reportsDirectory}",
         "{workspaceRoot}/coverage/e2e/mock-api-v2"
       ],
-      "options": {
-        "coverage.reportsDirectory": "../../coverage/e2e/mock-api-v2"
-      },
       "configurations": {
         "watch": {
           "watch": true
diff --git a/e2e/mock-api-v2/src/endpoints/custom-html.endpoint.ts b/e2e/mock-api-v2/src/endpoints/custom-html.endpoint.ts
index 5773f6cf3..6dd5015cc 100644
--- a/e2e/mock-api-v2/src/endpoints/custom-html.endpoint.ts
+++ b/e2e/mock-api-v2/src/endpoints/custom-html.endpoint.ts
@@ -5,17 +5,17 @@ import { Api, ApiResponse } from 'effect-http';
 import {
   DavinciAuthorizeHeaders,
   DavinciAuthorizeResponseHeaders,
-} from '../schemas/authorize.schema';
+} from '../schemas/authorize.schema.js';
 import {
   PingOneCustomHtmlRequestBody,
   PingOneRequestQuery,
-} from '../schemas/custom-html-template/custom-html-template-request.schema';
+} from '../schemas/custom-html-template/custom-html-template-request.schema.js';
 import {
   PingOneCustomHtmlResponseBody,
   PingOneCustomHtmlResponseErrorBody,
   PingOnePathParams,
-} from '../schemas/custom-html-template/custom-html-template-response.schema';
-import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema';
+} from '../schemas/custom-html-template/custom-html-template-response.schema.js';
+import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema.js';
 
 const customHtmlEndPoint = Api.addEndpoint(
   pipe(
diff --git a/e2e/mock-api-v2/src/endpoints/davinci-authorize.endpoint.ts b/e2e/mock-api-v2/src/endpoints/davinci-authorize.endpoint.ts
index 465f76ab9..5fbd3084b 100644
--- a/e2e/mock-api-v2/src/endpoints/davinci-authorize.endpoint.ts
+++ b/e2e/mock-api-v2/src/endpoints/davinci-authorize.endpoint.ts
@@ -7,9 +7,9 @@ import {
   DavinciAuthorizeHeaders,
   DavinciAuthorizeQuery,
   DavinciAuthorizeResponseHeaders,
-} from '../schemas/authorize.schema';
-import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema';
-import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema';
+} from '../schemas/authorize.schema.js';
+import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema.js';
+import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema.js';
 
 const davinciAuthorize = Api.addEndpoint(
   pipe(
diff --git a/e2e/mock-api-v2/src/endpoints/open-id-configuration.endpoint.ts b/e2e/mock-api-v2/src/endpoints/open-id-configuration.endpoint.ts
index 9afb75a09..fe041aed4 100644
--- a/e2e/mock-api-v2/src/endpoints/open-id-configuration.endpoint.ts
+++ b/e2e/mock-api-v2/src/endpoints/open-id-configuration.endpoint.ts
@@ -1,7 +1,7 @@
 import { Schema } from '@effect/schema';
 import { pipe } from 'effect';
 import { Api } from 'effect-http';
-import { openIdConfigurationResponseSchema } from '../schemas/open-id-configuration/open-id-configuration-response.schema';
+import { openIdConfigurationResponseSchema } from '../schemas/open-id-configuration/open-id-configuration-response.schema.js';
 
 const openidConfiguration = Api.addEndpoint(
   pipe(
diff --git a/e2e/mock-api-v2/src/endpoints/token.endpoint.ts b/e2e/mock-api-v2/src/endpoints/token.endpoint.ts
index 901399def..5bbffa469 100644
--- a/e2e/mock-api-v2/src/endpoints/token.endpoint.ts
+++ b/e2e/mock-api-v2/src/endpoints/token.endpoint.ts
@@ -2,7 +2,7 @@ import { Schema } from '@effect/schema';
 import { pipe } from 'effect';
 import { Api } from 'effect-http';
 
-import { TokenResponseBody } from '../schemas/token/token.schema';
+import { TokenResponseBody } from '../schemas/token/token.schema.js';
 
 const pingOneToken = Api.addEndpoint(
   pipe(
diff --git a/e2e/mock-api-v2/src/endpoints/userinfo.endpoint.ts b/e2e/mock-api-v2/src/endpoints/userinfo.endpoint.ts
index c6d7f5b97..7eb41b1f5 100644
--- a/e2e/mock-api-v2/src/endpoints/userinfo.endpoint.ts
+++ b/e2e/mock-api-v2/src/endpoints/userinfo.endpoint.ts
@@ -2,7 +2,7 @@ import { Schema } from '@effect/schema';
 import { pipe } from 'effect';
 import { Api, ApiResponse, Security } from 'effect-http';
 
-import { UserInfoSchema } from '../schemas/userinfo/userinfo.schema';
+import { UserInfoSchema } from '../schemas/userinfo/userinfo.schema.js';
 
 const userInfo = Api.addEndpoint(
   pipe(
diff --git a/e2e/mock-api-v2/src/example-server.ts b/e2e/mock-api-v2/src/example-server.ts
index b6b5c31fd..cb784c137 100644
--- a/e2e/mock-api-v2/src/example-server.ts
+++ b/e2e/mock-api-v2/src/example-server.ts
@@ -1,7 +1,7 @@
 import { RouterBuilder, Middlewares, ExampleServer } from 'effect-http';
 import { NodeRuntime } from '@effect/platform-node';
 import { NodeServer } from 'effect-http-node';
-import { apiSpec } from './spec';
+import { apiSpec } from './spec.js';
 
 const app = ExampleServer.make(apiSpec).pipe(RouterBuilder.build, Middlewares.errorLog);
 
diff --git a/e2e/mock-api-v2/src/handlers/authorize.handler.ts b/e2e/mock-api-v2/src/handlers/authorize.handler.ts
index 30a853b45..16249e9ee 100644
--- a/e2e/mock-api-v2/src/handlers/authorize.handler.ts
+++ b/e2e/mock-api-v2/src/handlers/authorize.handler.ts
@@ -2,9 +2,9 @@ import { toCookieHeader } from '@effect/platform/Cookies';
 import { Effect } from 'effect';
 import { RouterBuilder } from 'effect-http';
 
-import { Authorize } from '../services/authorize.service';
-import { CookieService } from '../services/cookie.service';
-import { apiSpec } from '../spec';
+import { Authorize } from '../services/authorize.service.js';
+import { CookieService } from '../services/cookie.service.js';
+import { apiSpec } from '../spec.js';
 
 const authorizeHandler = RouterBuilder.handler(apiSpec, 'DavinciAuthorize', ({ headers, query }) =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/handlers/custom-html-template.handler.ts b/e2e/mock-api-v2/src/handlers/custom-html-template.handler.ts
index f087d48da..129dbfd39 100644
--- a/e2e/mock-api-v2/src/handlers/custom-html-template.handler.ts
+++ b/e2e/mock-api-v2/src/handlers/custom-html-template.handler.ts
@@ -2,9 +2,9 @@ import { toCookieHeader } from '@effect/platform/Cookies';
 import { Effect } from 'effect';
 import { RouterBuilder } from 'effect-http';
 
-import { CookieService } from '../services/cookie.service';
-import { CustomHtmlTemplate } from '../services/custom-html-template.service';
-import { apiSpec } from '../spec';
+import { CookieService } from '../services/cookie.service.js';
+import { CustomHtmlTemplate } from '../services/custom-html-template.service.js';
+import { apiSpec } from '../spec.js';
 
 const customHtmlHandler = RouterBuilder.handler(
   apiSpec,
diff --git a/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts b/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts
index 6a535022b..2a1e3a8c7 100644
--- a/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts
+++ b/e2e/mock-api-v2/src/handlers/open-id-configuration.handler.ts
@@ -1,7 +1,7 @@
 import { Effect } from 'effect';
 import { RouterBuilder } from 'effect-http';
-import { apiSpec } from '../spec';
-import { openidConfigurationResponse } from '../responses/open-id-configuration';
+import { apiSpec } from '../spec.js';
+import { openidConfigurationResponse } from '../responses/open-id-configuration.js';
 
 const openidConfiguration = RouterBuilder.handler(apiSpec, 'openidConfiguration', () =>
   // eslint-disable-next-line require-yield
diff --git a/e2e/mock-api-v2/src/handlers/token.handler.ts b/e2e/mock-api-v2/src/handlers/token.handler.ts
index f8d763089..b3683ad83 100644
--- a/e2e/mock-api-v2/src/handlers/token.handler.ts
+++ b/e2e/mock-api-v2/src/handlers/token.handler.ts
@@ -1,7 +1,7 @@
 import { Effect } from 'effect';
 import { RouterBuilder } from 'effect-http';
-import { apiSpec } from '../spec';
-import { Tokens } from '../services/tokens.service';
+import { apiSpec } from '../spec.js';
+import { Tokens } from '../services/tokens.service.js';
 
 const tokenHandler = RouterBuilder.handler(apiSpec, 'PingOneToken', () =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/handlers/userinfo.handler.ts b/e2e/mock-api-v2/src/handlers/userinfo.handler.ts
index 40a2cefd6..31d017891 100644
--- a/e2e/mock-api-v2/src/handlers/userinfo.handler.ts
+++ b/e2e/mock-api-v2/src/handlers/userinfo.handler.ts
@@ -1,7 +1,7 @@
 import { Effect } from 'effect';
 import { RouterBuilder } from 'effect-http';
-import { apiSpec } from '../spec';
-import { UserInfo } from '../services/userinfo.service';
+import { apiSpec } from '../spec.js';
+import { UserInfo } from '../services/userinfo.service.js';
 
 const userInfoHandler = RouterBuilder.handler(apiSpec, 'UserInfo', (request, security) =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/helpers/cookie.ts b/e2e/mock-api-v2/src/helpers/cookie.ts
index 2b82e3531..7fb50a721 100644
--- a/e2e/mock-api-v2/src/helpers/cookie.ts
+++ b/e2e/mock-api-v2/src/helpers/cookie.ts
@@ -1,10 +1,10 @@
 import { Cookies } from '@effect/platform';
 import { Effect, Option, pipe } from 'effect';
 
-import { ResponseMapKeys, responseMap } from '../responses';
-import { returnSuccessResponseRedirect } from '../responses/return-success-redirect';
+import { ResponseMapKeys, responseMap } from '../responses/index.js';
+import { returnSuccessResponseRedirect } from '../responses/return-success-redirect.js';
 
-import { HeaderTypes } from '../types';
+import { HeaderTypes } from '../types/index.js';
 
 /**
  *
diff --git a/e2e/mock-api-v2/src/helpers/match.ts b/e2e/mock-api-v2/src/helpers/match.ts
index 720ef609d..42bad7690 100644
--- a/e2e/mock-api-v2/src/helpers/match.ts
+++ b/e2e/mock-api-v2/src/helpers/match.ts
@@ -1,8 +1,8 @@
 import { Schema } from '@effect/schema';
 import { Effect, Match } from 'effect';
 
-import { InvalidUsernamePassword, InvalidProtectNode } from '../errors';
-import { PingOneCustomHtmlRequestBody } from '../schemas/custom-html-template/custom-html-template-request.schema';
+import { InvalidUsernamePassword, InvalidProtectNode } from '../errors/index.js';
+import { PingOneCustomHtmlRequestBody } from '../schemas/custom-html-template/custom-html-template-request.schema.js';
 
 type PingRequestData = Schema.Schema.Type<
   typeof PingOneCustomHtmlRequestBody
diff --git a/e2e/mock-api-v2/src/helpers/test/cookie.test.ts b/e2e/mock-api-v2/src/helpers/test/cookie.test.ts
index af7f4acde..89f890c4a 100644
--- a/e2e/mock-api-v2/src/helpers/test/cookie.test.ts
+++ b/e2e/mock-api-v2/src/helpers/test/cookie.test.ts
@@ -1,9 +1,13 @@
 import { it, expect } from '@effect/vitest';
-import { getElementFromCookie, incrementCookieHeader, parseCookieHeaderForIndex } from '../cookie';
-import { HeaderTypes } from '../../types';
+import {
+  getElementFromCookie,
+  incrementCookieHeader,
+  parseCookieHeaderForIndex,
+} from '../cookie.js';
+import { HeaderTypes } from '../../types/index.js';
 import { Effect, Exit } from 'effect';
-import { responseMap } from '../../responses';
-import { returnSuccessResponseRedirect } from '../../responses/return-success-redirect';
+import { responseMap } from '../../responses/index.js';
+import { returnSuccessResponseRedirect } from '../../responses/return-success-redirect.js';
 
 it.effect('should parse a cookie header for an index value', () =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/helpers/test/match.test.ts b/e2e/mock-api-v2/src/helpers/test/match.test.ts
index a78d98a73..33c5eefff 100644
--- a/e2e/mock-api-v2/src/helpers/test/match.test.ts
+++ b/e2e/mock-api-v2/src/helpers/test/match.test.ts
@@ -1,5 +1,5 @@
 import { it, expect } from '@effect/vitest';
-import { PingRequestData, validator } from '../match';
+import { PingRequestData, validator } from '../match.js';
 import { Effect, Exit } from 'effect';
 
 it.effect('match validation function passes username password validation', () =>
diff --git a/e2e/mock-api-v2/src/main.ts b/e2e/mock-api-v2/src/main.ts
index 2685bcf96..b309f91bc 100644
--- a/e2e/mock-api-v2/src/main.ts
+++ b/e2e/mock-api-v2/src/main.ts
@@ -2,20 +2,20 @@ import { Config, Effect, Layer, pipe } from 'effect';
 import { RouterBuilder, Middlewares } from 'effect-http';
 import { NodeRuntime } from '@effect/platform-node';
 import { NodeServer } from 'effect-http-node';
-import { apiSpec } from './spec';
+import { apiSpec } from './spec.js';
 
-import { authorizeHandler } from './handlers/authorize.handler';
-import { customHtmlHandler } from './handlers/custom-html-template.handler';
-import { openidConfiguration } from './handlers/open-id-configuration.handler';
-import { tokenHandler } from './handlers/token.handler';
-import { userInfoHandler } from './handlers/userinfo.handler';
+import { authorizeHandler } from './handlers/authorize.handler.js';
+import { customHtmlHandler } from './handlers/custom-html-template.handler.js';
+import { openidConfiguration } from './handlers/open-id-configuration.handler.js';
+import { tokenHandler } from './handlers/token.handler.js';
+import { userInfoHandler } from './handlers/userinfo.handler.js';
 
-import { authorizeMock } from './services/authorize.service';
-import { CookieService, cookieServiceTest } from './services/cookie.service';
-import { mockCustomHtmlTemplate } from './services/custom-html-template.service';
-import { mockRequest } from './services/request.service';
-import { mockTokens } from './services/tokens.service';
-import { UserInfo, userInfoMock } from './services/userinfo.service';
+import { authorizeMock } from './services/authorize.service.js';
+import { CookieService, cookieServiceTest } from './services/cookie.service.js';
+import { mockCustomHtmlTemplate } from './services/custom-html-template.service.js';
+import { mockRequest } from './services/request.service.js';
+import { mockTokens } from './services/tokens.service.js';
+import { UserInfo, userInfoMock } from './services/userinfo.service.js';
 
 const app = RouterBuilder.make(apiSpec).pipe(
   RouterBuilder.handle('HealthCheck', () => Effect.succeed('Healthy!')),
diff --git a/e2e/mock-api-v2/src/responses/index.ts b/e2e/mock-api-v2/src/responses/index.ts
index ca9582841..a5759ae9a 100644
--- a/e2e/mock-api-v2/src/responses/index.ts
+++ b/e2e/mock-api-v2/src/responses/index.ts
@@ -1,7 +1,7 @@
 import { Array } from 'effect';
-import { UsernamePassword } from './username-password';
-import { PingProtectNode } from './custom-html-template/ping-protect-node';
-import { InvalidUsernamePassword } from './invalid-username-password';
+import { UsernamePassword } from './username-password.js';
+import { PingProtectNode } from './custom-html-template/ping-protect-node.js';
+import { InvalidUsernamePassword } from './invalid-username-password.js';
 
 type ResponseMapKeys = keyof typeof responseMap;
 const responseMap = {
diff --git a/e2e/mock-api-v2/src/services/authorize.service.ts b/e2e/mock-api-v2/src/services/authorize.service.ts
index 71022fbe8..7f342e64c 100644
--- a/e2e/mock-api-v2/src/services/authorize.service.ts
+++ b/e2e/mock-api-v2/src/services/authorize.service.ts
@@ -2,11 +2,11 @@ import { Schema } from '@effect/schema';
 import { Context, Effect, Layer, pipe } from 'effect';
 import { HttpError } from 'effect-http';
 
-import { getFirstElementAndRespond } from './mock-env-helpers';
-import { Request } from './request.service';
-import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema';
+import { getFirstElementAndRespond } from './mock-env-helpers/index.js';
+import { Request } from './request.service.js';
+import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema.js';
 
-import { HeaderTypes, QueryTypes } from '../types';
+import { HeaderTypes, QueryTypes } from '../types/index.js';
 
 type AuthorizeResponseBody = Schema.Schema.Type<typeof PingOneCustomHtmlResponseBody>;
 
diff --git a/e2e/mock-api-v2/src/services/cookie.service.ts b/e2e/mock-api-v2/src/services/cookie.service.ts
index cb9a940db..3d7070592 100644
--- a/e2e/mock-api-v2/src/services/cookie.service.ts
+++ b/e2e/mock-api-v2/src/services/cookie.service.ts
@@ -1,8 +1,8 @@
 import * as Cookies from '@effect/platform/Cookies';
 import { Effect, Context, Either } from 'effect';
 
-import { incrementCookieHeader } from '../helpers/cookie';
-import { HeaderTypes } from '../types';
+import { incrementCookieHeader } from '../helpers/cookie.js';
+import { HeaderTypes } from '../types/index.js';
 
 /*
  * Define the interface for the Cookie Service
diff --git a/e2e/mock-api-v2/src/services/custom-html-template.service.ts b/e2e/mock-api-v2/src/services/custom-html-template.service.ts
index a4dce3405..b40a72293 100644
--- a/e2e/mock-api-v2/src/services/custom-html-template.service.ts
+++ b/e2e/mock-api-v2/src/services/custom-html-template.service.ts
@@ -1,9 +1,14 @@
 import { Context, Effect, Layer } from 'effect';
 import { HttpError } from 'effect-http';
-import { Request } from './request.service';
+import { Request } from './request.service.js';
 
-import { CustomHtmlRequestBody, CustomHtmlResponseBody, HeaderTypes, QueryTypes } from '../types';
-import { validateCustomHtmlRequest } from './mock-env-helpers';
+import {
+  CustomHtmlRequestBody,
+  CustomHtmlResponseBody,
+  HeaderTypes,
+  QueryTypes,
+} from '../types/index.js';
+import { validateCustomHtmlRequest } from './mock-env-helpers/index.js';
 
 class CustomHtmlTemplate extends Context.Tag('@services/CustomHtmlTemplate')<
   CustomHtmlTemplate,
diff --git a/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts b/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts
index 83e52eddd..098ca6b22 100644
--- a/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts
+++ b/e2e/mock-api-v2/src/services/mock-env-helpers/index.ts
@@ -1,12 +1,12 @@
 import { Schema } from '@effect/schema';
 import { Array, Effect, Option, pipe } from 'effect';
 
-import { UnableToFindNextStep } from '../../errors';
-import { PingOneCustomHtmlRequestBody } from '../../schemas/custom-html-template/custom-html-template-request.schema';
-import { ResponseMapKeys, responseMap } from '../../responses';
+import { UnableToFindNextStep } from '../../errors/index.js';
+import { PingOneCustomHtmlRequestBody } from '../../schemas/custom-html-template/custom-html-template-request.schema.js';
+import { ResponseMapKeys, responseMap } from '../../responses/index.js';
 
-import { CustomHtmlRequestBody, QueryTypes } from '../../types';
-import { validator } from '../../helpers/match';
+import { CustomHtmlRequestBody, QueryTypes } from '../../types/index.js';
+import { validator } from '../../helpers/match.js';
 
 type DavinciFormData = Schema.Schema.Type<
   typeof PingOneCustomHtmlRequestBody
diff --git a/e2e/mock-api-v2/src/services/mock-env-helpers/tests/index.test.ts b/e2e/mock-api-v2/src/services/mock-env-helpers/tests/index.test.ts
index 2b7caf46d..c706d64a4 100644
--- a/e2e/mock-api-v2/src/services/mock-env-helpers/tests/index.test.ts
+++ b/e2e/mock-api-v2/src/services/mock-env-helpers/tests/index.test.ts
@@ -6,10 +6,10 @@ import {
   getNextStep,
   mapDataToValue,
   validateCustomHtmlRequest,
-} from '..';
-import { CustomHtmlRequestBody, QueryTypes } from '../../../types';
-import { PingProtectNode } from '../../../responses/custom-html-template/ping-protect-node';
-import { UsernamePassword } from '../../../responses/username-password';
+} from '../index.js';
+import { CustomHtmlRequestBody, QueryTypes } from '../../../types/index.js';
+import { PingProtectNode } from '../../../responses/custom-html-template/ping-protect-node.js';
+import { UsernamePassword } from '../../../responses/username-password.js';
 
 it('should map data to value in a DavinciFormData', () => {
   const data = Option.some({
diff --git a/e2e/mock-api-v2/src/services/request.service.ts b/e2e/mock-api-v2/src/services/request.service.ts
index f8390eabd..8f1ab0414 100644
--- a/e2e/mock-api-v2/src/services/request.service.ts
+++ b/e2e/mock-api-v2/src/services/request.service.ts
@@ -1,10 +1,10 @@
 import { Effect, Context, pipe, Layer } from 'effect';
 import { HttpError } from 'effect-http';
 
-import { getElementFromCookie } from '../helpers/cookie';
-import { getNextStep } from './mock-env-helpers';
+import { getElementFromCookie } from '../helpers/cookie.js';
+import { getNextStep } from './mock-env-helpers/index.js';
 
-import { HeaderTypes, QueryTypes } from '../types';
+import { HeaderTypes, QueryTypes } from '../types/index.js';
 
 type Init<Headers extends HeaderTypes, Query extends QueryTypes, Body = null> = {
   headers: Headers;
diff --git a/e2e/mock-api-v2/src/services/tests/authorize.service.test.ts b/e2e/mock-api-v2/src/services/tests/authorize.service.test.ts
index 4636ce56f..a3cd13663 100644
--- a/e2e/mock-api-v2/src/services/tests/authorize.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/authorize.service.test.ts
@@ -1,8 +1,8 @@
 import { it, expect } from '@effect/vitest';
 import { Effect, Layer } from 'effect';
-import { Authorize, authorizeMock } from '../authorize.service';
-import { mockRequest } from '../request.service';
-import { PingProtectNode } from '../../responses/custom-html-template/ping-protect-node';
+import { Authorize, authorizeMock } from '../authorize.service.js';
+import { mockRequest } from '../request.service.js';
+import { PingProtectNode } from '../../responses/custom-html-template/ping-protect-node.js';
 
 const queryParams = {
   response_mode: 'pi.flow',
diff --git a/e2e/mock-api-v2/src/services/tests/cookie.service.test.ts b/e2e/mock-api-v2/src/services/tests/cookie.service.test.ts
index afe210e05..a792f15e6 100644
--- a/e2e/mock-api-v2/src/services/tests/cookie.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/cookie.service.test.ts
@@ -1,5 +1,5 @@
 import { it, expect } from '@effect/vitest';
-import { CookieService, cookieServiceTest } from '../cookie.service';
+import { CookieService, cookieServiceTest } from '../cookie.service.js';
 import { Effect, Either } from 'effect';
 import { Cookies } from '@effect/platform';
 
diff --git a/e2e/mock-api-v2/src/services/tests/custom-html-template.service.test.ts b/e2e/mock-api-v2/src/services/tests/custom-html-template.service.test.ts
index 490fad2d4..5cd4024b7 100644
--- a/e2e/mock-api-v2/src/services/tests/custom-html-template.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/custom-html-template.service.test.ts
@@ -1,8 +1,8 @@
 import { it, expect } from '@effect/vitest';
-import { CustomHtmlTemplate, mockCustomHtmlTemplate } from '../custom-html-template.service';
+import { CustomHtmlTemplate, mockCustomHtmlTemplate } from '../custom-html-template.service.js';
 import { Effect, Exit, Layer } from 'effect';
-import { mockRequest } from '../request.service';
-import { UsernamePassword } from '../../responses/username-password';
+import { mockRequest } from '../request.service.js';
+import { UsernamePassword } from '../../responses/username-password.js';
 
 const queryParams = {
   response_mode: 'pi.flow',
diff --git a/e2e/mock-api-v2/src/services/tests/request.service.test.ts b/e2e/mock-api-v2/src/services/tests/request.service.test.ts
index f7097046a..8a45001ea 100644
--- a/e2e/mock-api-v2/src/services/tests/request.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/request.service.test.ts
@@ -1,8 +1,8 @@
 import { it, expect } from '@effect/vitest';
-import { Request, mockRequest } from '../request.service';
+import { Request, mockRequest } from '../request.service.js';
 import { Effect } from 'effect';
-import { CustomHtmlResponseBody } from '../custom-html-template.service';
-import { UsernamePassword } from '../../responses/username-password';
+import { CustomHtmlResponseBody } from '../custom-html-template.service.js';
+import { UsernamePassword } from '../../responses/username-password.js';
 
 it('should make a get request', () =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/services/tests/token.service.test.ts b/e2e/mock-api-v2/src/services/tests/token.service.test.ts
index 212670a39..4447e420f 100644
--- a/e2e/mock-api-v2/src/services/tests/token.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/token.service.test.ts
@@ -1,8 +1,8 @@
 import { it, expect } from '@effect/vitest';
-import { Tokens, mockTokens } from '../tokens.service';
+import { Tokens, mockTokens } from '../tokens.service.js';
 import { Effect, Exit, Layer } from 'effect';
-import { mockRequest } from '../request.service';
-import { tokenResponseBody } from '../../responses/token/token';
+import { mockRequest } from '../request.service.js';
+import { tokenResponseBody } from '../../responses/token/token.js';
 
 it.effect('should return tokens', () =>
   Effect.gen(function* () {
diff --git a/e2e/mock-api-v2/src/services/tests/userinfo.service.test.ts b/e2e/mock-api-v2/src/services/tests/userinfo.service.test.ts
index 548150c75..6b57b6875 100644
--- a/e2e/mock-api-v2/src/services/tests/userinfo.service.test.ts
+++ b/e2e/mock-api-v2/src/services/tests/userinfo.service.test.ts
@@ -1,6 +1,6 @@
 import { expect, it } from '@effect/vitest';
-import { UserInfo, userInfoMock } from '../userinfo.service';
-import { userInfoResponse } from '../../responses/userinfo/userinfo';
+import { UserInfo, userInfoMock } from '../userinfo.service.js';
+import { userInfoResponse } from '../../responses/userinfo/userinfo.js';
 import { Effect } from 'effect';
 
 it.effect('should get userinfo', () =>
diff --git a/e2e/mock-api-v2/src/services/tokens.service.ts b/e2e/mock-api-v2/src/services/tokens.service.ts
index 7405559fa..b1a79adf8 100644
--- a/e2e/mock-api-v2/src/services/tokens.service.ts
+++ b/e2e/mock-api-v2/src/services/tokens.service.ts
@@ -2,11 +2,11 @@ import { Schema } from '@effect/schema';
 import { Context, Effect, Layer } from 'effect';
 import { HttpError } from 'effect-http';
 
-import { Request } from './request.service';
-import { tokenResponseBody } from '../responses/token/token';
-import { TokenResponseBody } from '../schemas/token/token.schema';
+import { Request } from './request.service.js';
+import { tokenResponseBody } from '../responses/token/token.js';
+import { TokenResponseBody } from '../schemas/token/token.schema.js';
 
-import { HeaderTypes } from '../types';
+import { HeaderTypes } from '../types/index.js';
 
 type TokensResponseBody = Schema.Schema.Type<typeof TokenResponseBody>;
 
diff --git a/e2e/mock-api-v2/src/services/userinfo.service.ts b/e2e/mock-api-v2/src/services/userinfo.service.ts
index 3a60fa8c9..6e70633b1 100644
--- a/e2e/mock-api-v2/src/services/userinfo.service.ts
+++ b/e2e/mock-api-v2/src/services/userinfo.service.ts
@@ -2,8 +2,8 @@ import { Schema } from '@effect/schema';
 import { Effect, Context } from 'effect';
 import { HttpError } from 'effect-http';
 
-import { userInfoResponse } from '../responses/userinfo/userinfo';
-import { UserInfoSchema } from '../schemas/userinfo/userinfo.schema';
+import { userInfoResponse } from '../responses/userinfo/userinfo.js';
+import { UserInfoSchema } from '../schemas/userinfo/userinfo.schema.js';
 
 /***
  * This file should be converted to a Layer that uses Request
diff --git a/e2e/mock-api-v2/src/spec.ts b/e2e/mock-api-v2/src/spec.ts
index 14af203b2..cbe43a4c0 100644
--- a/e2e/mock-api-v2/src/spec.ts
+++ b/e2e/mock-api-v2/src/spec.ts
@@ -2,11 +2,11 @@ import { pipe } from 'effect';
 import { Schema } from '@effect/schema';
 import { Api } from 'effect-http';
 
-import { openidConfiguration } from './endpoints/open-id-configuration.endpoint';
-import { davinciAuthorize } from './endpoints/davinci-authorize.endpoint';
-import { customHtmlEndPoint } from './endpoints/custom-html.endpoint';
-import { pingOneToken } from './endpoints/token.endpoint';
-import { userInfo } from './endpoints/userinfo.endpoint';
+import { openidConfiguration } from './endpoints/open-id-configuration.endpoint.js';
+import { davinciAuthorize } from './endpoints/davinci-authorize.endpoint.js';
+import { customHtmlEndPoint } from './endpoints/custom-html.endpoint.js';
+import { pingOneToken } from './endpoints/token.endpoint.js';
+import { userInfo } from './endpoints/userinfo.endpoint.js';
 
 const apiSpec = pipe(
   Api.make({ title: 'MockApi' }),
diff --git a/e2e/mock-api-v2/src/types/index.ts b/e2e/mock-api-v2/src/types/index.ts
index ffada56f2..a038ff975 100644
--- a/e2e/mock-api-v2/src/types/index.ts
+++ b/e2e/mock-api-v2/src/types/index.ts
@@ -1,11 +1,11 @@
 import { Schema } from '@effect/schema';
-import { DavinciAuthorizeHeaders, DavinciAuthorizeQuery } from '../schemas/authorize.schema';
+import { DavinciAuthorizeHeaders, DavinciAuthorizeQuery } from '../schemas/authorize.schema.js';
 import {
   PingOneCustomHtmlRequestBody,
   PingOneRequestQuery,
-} from '../schemas/custom-html-template/custom-html-template-request.schema';
-import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema';
-import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema';
+} from '../schemas/custom-html-template/custom-html-template-request.schema.js';
+import { PingOneCustomHtmlResponseBody } from '../schemas/custom-html-template/custom-html-template-response.schema.js';
+import { SuccessResponseRedirect } from '../schemas/return-success-response-redirect.schema.js';
 
 type QueryTypes =
   | Schema.Schema.Type<typeof DavinciAuthorizeQuery>
diff --git a/e2e/mock-api-v2/tsconfig.spec.json b/e2e/mock-api-v2/tsconfig.spec.json
index 22b25aaf7..62604619c 100644
--- a/e2e/mock-api-v2/tsconfig.spec.json
+++ b/e2e/mock-api-v2/tsconfig.spec.json
@@ -6,11 +6,11 @@
     "moduleResolution": "NodeNext",
     "target": "ES2020",
     "types": [
+      "vitest/vitest",
       "vitest/globals",
       "vitest/importMeta",
       "vite/client",
-      "node",
-      "vitest"
+      "node"
     ]
   },
   "include": [
diff --git a/e2e/mock-api-v2/vite.config.ts b/e2e/mock-api-v2/vite.config.ts
index 31246360f..f920e8de4 100644
--- a/e2e/mock-api-v2/vite.config.ts
+++ b/e2e/mock-api-v2/vite.config.ts
@@ -1,5 +1,4 @@
-/// <reference types='vitest' />
-import { defineConfig } from 'vite';
+import { defineConfig } from 'vitest/config';
 
 export default defineConfig({
   root: __dirname,
@@ -14,9 +13,10 @@ export default defineConfig({
     environment: 'jsdom',
     include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
 
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     coverage: {
-      reportsDirectory: '../../coverage/e2e/mock-api-v2',
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
       provider: 'v8',
     },
   },
diff --git a/e2e/token-vault-interceptor/vite.config.ts b/e2e/token-vault-interceptor/vite.config.ts
index 93f1b540c..20577a512 100644
--- a/e2e/token-vault-interceptor/vite.config.ts
+++ b/e2e/token-vault-interceptor/vite.config.ts
@@ -33,9 +33,9 @@ export default defineConfig({
     passWithNoTests: true,
     include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
 
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     coverage: {
-      reportsDirectory: '../../coverage/e2e/token-vault-interceptor',
+      reportsDirectory: './coverage',
       provider: 'v8',
     },
   },
diff --git a/nx.json b/nx.json
index 4acbf49ca..f53d3da41 100644
--- a/nx.json
+++ b/nx.json
@@ -38,6 +38,7 @@
     "@nx/vite:test": {
       "dependsOn": ["^test"],
       "inputs": ["noMarkdown", "^noMarkdown"],
+      "outputs": ["{projectRoot}/coverage"],
       "cache": true
     },
     "@nx/eslint:lint": {
@@ -69,7 +70,8 @@
     "@nx/js:tsc": {
       "cache": true,
       "dependsOn": ["^build"],
-      "inputs": ["production", "^production"]
+      "inputs": ["production", "^production"],
+      "outputs": ["{projectRoot}/dist"]
     }
   },
   "parallel": 1,
diff --git a/package.json b/package.json
index 5a0f34e27..ff8b240f4 100644
--- a/package.json
+++ b/package.json
@@ -67,7 +67,7 @@
     "@typescript-eslint/parser": "7.16.1",
     "@typescript-eslint/typescript-estree": "5.59.5",
     "@vitejs/plugin-basic-ssl": "1.1.0",
-    "@vitest/coverage-v8": "^1.4.0",
+    "@vitest/coverage-v8": "^1.5.0",
     "@vitest/ui": "^1.4.0",
     "conventional-changelog-conventionalcommits": "^7.0.2",
     "cookie-parser": "^1.4.6",
diff --git a/packages/davinci-client/.eslintignore b/packages/davinci-client/.eslintignore
index 58d56dc4f..cd4b8a20f 100644
--- a/packages/davinci-client/.eslintignore
+++ b/packages/davinci-client/.eslintignore
@@ -7,3 +7,4 @@ LICENSE
 dist
 .eslintignore
 docs
+coverage
diff --git a/packages/davinci-client/project.json b/packages/davinci-client/project.json
index 575e28468..7369a18a1 100644
--- a/packages/davinci-client/project.json
+++ b/packages/davinci-client/project.json
@@ -25,14 +25,7 @@
         {
           "externalDependencies": ["vitest"]
         }
-      ],
-      "outputs": [
-        "{projectRoot}/{options.coverage.reportsDirectory}",
-        "{workspaceRoot}/coverage/packages/davinci-client"
-      ],
-      "options": {
-        "coverage.reportsDirectory": "../../coverage/packages/davinci-client"
-      }
+      ]
     },
     "lint": {
       "inputs": [
diff --git a/packages/davinci-client/tsconfig.spec.json b/packages/davinci-client/tsconfig.spec.json
index 3c002c215..0ce2e4576 100644
--- a/packages/davinci-client/tsconfig.spec.json
+++ b/packages/davinci-client/tsconfig.spec.json
@@ -7,7 +7,7 @@
       "vitest/importMeta",
       "vite/client",
       "node",
-      "vitest"
+      "vitest/vitest"
     ]
   },
   "include": [
diff --git a/packages/davinci-client/vite.config.ts b/packages/davinci-client/vite.config.ts
index e8db97ec1..c3a6afc29 100644
--- a/packages/davinci-client/vite.config.ts
+++ b/packages/davinci-client/vite.config.ts
@@ -46,7 +46,6 @@ export default defineConfig({
     reportCompressedSize: true,
     commonjsOptions: { transformMixedEsModules: true },
   },
-
   test: {
     cache: {
       dir: '../../node_modules/.vitest',
@@ -54,7 +53,11 @@ export default defineConfig({
     globals: true,
     environment: 'jsdom',
     include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
-    reporters: ['default'],
-    coverage: { reportsDirectory: '../../coverage/packages/davinci-client', provider: 'v8' },
+    reporters: ['default', 'junit'],
+    coverage: {
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
+      provider: 'v8',
+    },
   },
 });
diff --git a/packages/device-client/.eslintignore b/packages/device-client/.eslintignore
index 58d56dc4f..cd4b8a20f 100644
--- a/packages/device-client/.eslintignore
+++ b/packages/device-client/.eslintignore
@@ -7,3 +7,4 @@ LICENSE
 dist
 .eslintignore
 docs
+coverage
diff --git a/packages/device-client/tsconfig.spec.json b/packages/device-client/tsconfig.spec.json
index 3c002c215..55d312d19 100644
--- a/packages/device-client/tsconfig.spec.json
+++ b/packages/device-client/tsconfig.spec.json
@@ -3,11 +3,11 @@
   "compilerOptions": {
     "outDir": "../../dist/out-tsc",
     "types": [
+      "vitest/vitest",
       "vitest/globals",
       "vitest/importMeta",
       "vite/client",
-      "node",
-      "vitest"
+      "node"
     ]
   },
   "include": [
diff --git a/packages/device-client/vite.config.ts b/packages/device-client/vite.config.ts
index 1fd2e9e0e..e76973706 100644
--- a/packages/device-client/vite.config.ts
+++ b/packages/device-client/vite.config.ts
@@ -29,15 +29,17 @@ export default defineConfig(() => ({
     }),
   ],
   test: {
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     globals: true,
     setupFiles: ['./vitest.setup.ts'],
     passWithNoTests: true,
     watch: !process.env['CI'],
     coverage: {
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
       provider: 'v8',
-      reportsDirectory: '../../coverage/packages/self-service',
     },
+
     deps: {
       optimizer: {
         web: {
diff --git a/packages/javascript-sdk/.eslintignore b/packages/javascript-sdk/.eslintignore
index a1d4f4e97..38bed6b48 100644
--- a/packages/javascript-sdk/.eslintignore
+++ b/packages/javascript-sdk/.eslintignore
@@ -6,3 +6,4 @@ LICENSE
 .bin
 dist
 docs
+coverage
diff --git a/packages/javascript-sdk/package.json b/packages/javascript-sdk/package.json
index 6dcbc6406..ad8ece6c5 100644
--- a/packages/javascript-sdk/package.json
+++ b/packages/javascript-sdk/package.json
@@ -50,8 +50,5 @@
       }
     }
   },
-  "type": "module",
-  "devDependencies": {
-    "vitest": "^1.4.0"
-  }
+  "type": "module"
 }
diff --git a/packages/javascript-sdk/tests/integration/fr-auth.test.ts b/packages/javascript-sdk/tests/integration/fr-auth.test.ts
index 9716ac51b..5ff76d65d 100644
--- a/packages/javascript-sdk/tests/integration/fr-auth.test.ts
+++ b/packages/javascript-sdk/tests/integration/fr-auth.test.ts
@@ -11,23 +11,25 @@
 import { vi, expect, describe, it, afterAll } from 'vitest';
 import type PasswordCallback from '../../src/fr-auth/callbacks/password-callback';
 import { CallbackType } from '../../src/auth/enums';
-import Config from '../../src/config';
-import FRAuth from '../../src/fr-auth';
+import Config from '../../src/config/index';
+import FRAuth from '../../src/fr-auth/index';
 import type NameCallback from '../../src/fr-auth/callbacks/name-callback';
 import type FRStep from '../../src/fr-auth/fr-step';
 import { rawResponse } from './fr-auth.mock.data';
 
-vi.mock('../../src/config', () => {
+vi.mock('../../src/config/index', () => {
   return {
-    set: (conf) => conf,
-    // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
-    get() {
-      return {
-        serverConfig: {
-          baseUrl: 'https://openam.example.com/am/',
-          timeout: 0,
-        },
-      };
+    default: {
+      set: (conf) => conf,
+      // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
+      get() {
+        return {
+          serverConfig: {
+            baseUrl: 'https://openam.example.com/am/',
+            timeout: 0,
+          },
+        };
+      },
     },
   };
 });
@@ -57,9 +59,9 @@ describe('Test FRAuth.next functionality', () => {
     ).setPassword('Password1!');
 
     expect(stage).toBe('UsernamePassword');
-    expect(step.payload.callbacks[0].input[0].name).toBe('IDToken1');
-    expect(step.payload.callbacks[0].input[0].value).toBe('jsmith');
-    expect(step.payload.callbacks[1].input[0].name).toBe('IDToken2');
-    expect(step.payload.callbacks[1].input[0].value).toBe('Password1!');
+    expect(step.payload.callbacks![0].input![0].name).toBe('IDToken1');
+    expect(step.payload.callbacks![0].input![0].value).toBe('jsmith');
+    expect(step.payload.callbacks![1].input![0].name).toBe('IDToken2');
+    expect(step.payload.callbacks![1].input![0].value).toBe('Password1!');
   });
 });
diff --git a/packages/javascript-sdk/tests/integration/http-client.test.ts b/packages/javascript-sdk/tests/integration/http-client.test.ts
index 20698f59d..f09c5957f 100644
--- a/packages/javascript-sdk/tests/integration/http-client.test.ts
+++ b/packages/javascript-sdk/tests/integration/http-client.test.ts
@@ -9,7 +9,7 @@
  */
 import { vi, expect, describe, it, afterAll, beforeEach } from 'vitest';
 import HttpClient from '../../src/http-client/index';
-import TokenStorage from '../../src/token-storage';
+import TokenStorage from '../../src/token-storage/index';
 import {
   authzByTreeReqOptionsForREST,
   authzByTreeReqOptionsForIG,
@@ -32,23 +32,25 @@ import {
 
 // TODO: figure out how to move these mock functions in separate file
 // Because Jest hoists mocks above the imports, importing doesn't work :(
-vi.mock('../../src/token-storage');
-vi.mock('../../src/config', () => {
+vi.mock('../../src/token-storage/index');
+vi.mock('../../src/config/index', () => {
   return {
-    // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
-    get() {
-      return {
-        serverConfig: {
-          baseUrl: 'https://openam.example.com/am/',
-          timeout: 0,
-        },
-      };
+    default: {
+      // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
+      get() {
+        return {
+          serverConfig: {
+            baseUrl: 'https://openam.example.com/am/',
+            timeout: 0,
+          },
+        };
+      },
     },
   };
 });
 
-vi.mock('../../src/http-client/index', () => {
-  const originalHttpClient = vi.requireActual('../../src/http-client/index');
+vi.mock('../../src/http-client/index', async () => {
+  const originalHttpClient = await vi.importActual('../../src/http-client/index');
   const mockResponse = vi.fn(function (options: any): Promise<Response> {
     if (options.url === 'https://request-auth-by-tree.com/ig') {
       return Promise.resolve(mockAuthzByTreeResFromIG);
@@ -64,10 +66,12 @@ vi.mock('../../src/http-client/index', () => {
     }
   });
   return {
-    request: originalHttpClient.default.request,
-    stepIterator: vi.fn().mockResolvedValue({}),
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    _request: mockResponse,
+    default: {
+      request: (originalHttpClient.default as typeof HttpClient).request,
+      stepIterator: vi.fn().mockResolvedValue({}),
+      // eslint-disable-next-line @typescript-eslint/no-explicit-any
+      _request: mockResponse,
+    },
   };
 });
 
diff --git a/packages/javascript-sdk/tests/integration/oauth2-client.test.ts b/packages/javascript-sdk/tests/integration/oauth2-client.test.ts
index 12ab06d44..18c1c14be 100644
--- a/packages/javascript-sdk/tests/integration/oauth2-client.test.ts
+++ b/packages/javascript-sdk/tests/integration/oauth2-client.test.ts
@@ -1,42 +1,49 @@
 import { vi, afterAll, describe, it, expect } from 'vitest';
-import OAuth2Client from '../../src/oauth2-client';
+import OAuth2Client from '../../src/oauth2-client/index';
 import PKCE from '../../src/util/pkce';
-import { ResponseType } from '../../src/oauth2-client';
+import { ResponseType } from '../../src/oauth2-client/index';
 import { FRLogger } from '../../src/util/logger';
 
-vi.mock('../../src/config', () => {
+vi.mock('../../src/config/index', () => {
   return {
-    // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
-    get() {
-      return {
-        redirectUrl: 'https://sdkapp.example.com/',
-        clientId: 'OAuth2ClientID',
-        scope: 'openid email profile',
-        serverConfig: {
-          baseUrl: 'https://openam.example.com/am/',
-          timeout: '3000',
-        },
-        realmPath: '/alpha',
-      };
+    default: {
+      // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
+      get() {
+        return {
+          redirectUrl: 'https://sdkapp.example.com/',
+          clientId: 'OAuth2ClientID',
+          scope: 'openid email profile',
+          serverConfig: {
+            baseUrl: 'https://openam.example.com/am/',
+            timeout: '3000',
+          },
+          realmPath: '/alpha',
+        };
+      },
     },
   };
 });
+
 vi.mock('../../src/util/pkce', () => {
   return {
-    createVerifier(): string {
-      return 'abcd';
-    },
-    createState(): string {
-      return '1234';
-    },
-    createChallenge(): string {
-      return 'wxyz';
+    default: {
+      createVerifier(): string {
+        return 'abcd';
+      },
+      createState(): string {
+        return '1234';
+      },
+      createChallenge(): string {
+        return 'wxyz';
+      },
     },
   };
 });
+
 afterAll(() => {
   vi.clearAllMocks();
 });
+
 describe('Test OAuth2Client methods', () => {
   it('should construct proper authorization URL', async () => {
     const verifier = PKCE.createVerifier();
diff --git a/packages/javascript-sdk/tsconfig.json b/packages/javascript-sdk/tsconfig.json
index 395b2b1e8..51449353a 100644
--- a/packages/javascript-sdk/tsconfig.json
+++ b/packages/javascript-sdk/tsconfig.json
@@ -1,6 +1,15 @@
 {
   "extends": "../../tsconfig.base.json",
-  "compilerOptions": {},
+  "compilerOptions": {
+    "module": "ES2020",
+    "forceConsistentCasingInFileNames": true,
+    "strict": true,
+    "noImplicitOverride": false,
+    "noPropertyAccessFromIndexSignature": false,
+    "skipLibCheck": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true
+  },
   "references": [
     {
       "path": "./tsconfig.spec.json"
diff --git a/packages/javascript-sdk/tsconfig.spec.json b/packages/javascript-sdk/tsconfig.spec.json
index 71b2dd6bc..dfd5c8d0a 100644
--- a/packages/javascript-sdk/tsconfig.spec.json
+++ b/packages/javascript-sdk/tsconfig.spec.json
@@ -19,6 +19,10 @@
     "src/**/*.spec.js",
     "src/**/*.test.jsx",
     "src/**/*.spec.jsx",
-    "src/**/*.d.ts"
+    "src/**/*.d.ts",
+    "src/**/*.mock.*",
+    "tests/**/*.test.ts",
+    "tests/**/*.spec.ts",
+    "tests/**/*.mock*.ts"
   ]
 }
diff --git a/packages/javascript-sdk/vite.config.ts b/packages/javascript-sdk/vite.config.ts
index 8c8b36735..1f576eeef 100644
--- a/packages/javascript-sdk/vite.config.ts
+++ b/packages/javascript-sdk/vite.config.ts
@@ -1,4 +1,3 @@
-/// <reference types='vitest' />
 import { defineConfig } from 'vite';
 import dts from 'vite-plugin-dts';
 import { copyFileSync } from 'fs';
@@ -43,13 +42,14 @@ export default defineConfig({
   test: {
     globals: true,
     environment: 'jsdom',
-    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+    include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', 'tests/**/*.test.ts'],
     watch: !process.env['CI'],
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     setupFiles: ['./vitest.setup.ts'],
     coverage: {
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
       provider: 'v8',
-      reportsDirectory: '../../coverage/packages/javascript-sdk',
     },
     deps: {
       optimizer: {
diff --git a/packages/ping-protect/.eslintignore b/packages/ping-protect/.eslintignore
index 89fe00387..9390a92a9 100644
--- a/packages/ping-protect/.eslintignore
+++ b/packages/ping-protect/.eslintignore
@@ -8,3 +8,4 @@ dist
 src/lib/ping-signals-sdk.js
 .eslintignore
 docs
+coverage
diff --git a/packages/ping-protect/vite.config.ts b/packages/ping-protect/vite.config.ts
index 410751160..e729dcf3a 100644
--- a/packages/ping-protect/vite.config.ts
+++ b/packages/ping-protect/vite.config.ts
@@ -29,13 +29,14 @@ export default defineConfig({
     }),
   ],
   test: {
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     globals: true,
     setupFiles: ['./vitest.setup.ts'],
     watch: !process.env['CI'],
     coverage: {
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
       provider: 'v8',
-      reportsDirectory: '../../coverage/packages/ping-protect',
     },
     deps: {
       optimizer: {
diff --git a/packages/token-vault/.eslintignore b/packages/token-vault/.eslintignore
index 5ac9058f3..f00cfd6c3 100644
--- a/packages/token-vault/.eslintignore
+++ b/packages/token-vault/.eslintignore
@@ -7,3 +7,4 @@ LICENSE
 .bin
 dist
 docs
+coverage
diff --git a/packages/token-vault/vite.config.ts b/packages/token-vault/vite.config.ts
index 1ea4f7bbd..118bc5c1e 100644
--- a/packages/token-vault/vite.config.ts
+++ b/packages/token-vault/vite.config.ts
@@ -36,10 +36,11 @@ export default defineConfig({
     environment: 'jsdom',
     include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
     pool: 'forks',
-    reporters: ['default'],
+    reporters: ['default', 'junit'],
     watch: !process.env['CI'],
     coverage: {
-      reportsDirectory: '../../coverage/packages/token-vault',
+      enabled: Boolean(process.env['CI']),
+      reportsDirectory: './coverage',
       provider: 'v8',
     },
   },
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bc0a6f590..20852a0a3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -126,7 +126,7 @@ importers:
         specifier: 1.1.0
         version: 1.1.0(vite@5.4.8(@types/node@18.19.26)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0))
       '@vitest/coverage-v8':
-        specifier: ^1.4.0
+        specifier: ^1.5.0
         version: 1.5.0(vitest@1.5.0(@types/node@18.19.26)(@vitest/ui@1.5.0)(jsdom@22.1.0)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0))
       '@vitest/ui':
         specifier: ^1.4.0
@@ -297,6 +297,8 @@ importers:
 
   e2e/mock-api: {}
 
+  e2e/mock-api-v2: {}
+
   e2e/token-vault-app:
     dependencies:
       '@forgerock/javascript-sdk':
@@ -357,11 +359,7 @@ importers:
         specifier: ^1.4.0
         version: 1.5.0(@types/node@20.16.11)(@vitest/ui@1.5.0)(jsdom@22.1.0)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0)
 
-  packages/javascript-sdk:
-    devDependencies:
-      vitest:
-        specifier: ^1.4.0
-        version: 1.5.0(@types/node@20.16.11)(@vitest/ui@1.5.0)(jsdom@22.1.0)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0)
+  packages/javascript-sdk: {}
 
   packages/ping-protect:
     dependencies:
@@ -7117,6 +7115,7 @@ packages:
         integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==,
       }
     engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 }
+    deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
     hasBin: true
 
   espree@9.6.1:
@@ -17901,7 +17900,7 @@ snapshots:
       pathe: 1.1.2
       picocolors: 1.1.0
       sirv: 2.0.4
-      vitest: 1.5.0(@types/node@20.16.11)(@vitest/ui@1.5.0)(jsdom@22.1.0)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0)
+      vitest: 1.5.0(@types/node@18.19.26)(@vitest/ui@1.5.0)(jsdom@22.1.0)(less@4.1.3)(sass@1.75.0)(stylus@0.64.0)(terser@5.33.0)
 
   '@vitest/utils@1.5.0':
     dependencies: