···11+## [2.5.2](https://github.com/usekaneo/kaneo/compare/v2.5.1...v2.5.2) (2026-04-02)
22+33+44+### Bug Fixes
55+66+* accept dbOrTx, add subscribeToEvent, fix status lookup,error handling, error toast, french ([2ce9f59](https://github.com/usekaneo/kaneo/commit/2ce9f590523b8cdd910e638faeff25add6109e4c))
77+* **api:** create projects transactionally ([f15d34c](https://github.com/usekaneo/kaneo/commit/f15d34c6f2219c43a167043e677f9a6adf718e40))
88+* **api:** document health route and harden asset auth handling ([704376e](https://github.com/usekaneo/kaneo/commit/704376e440b8822b20fb18787dfa7f033ab723da))
99+* **ci,github:** tighten workflow token scope and preserve zero task numbers ([a56e8cd](https://github.com/usekaneo/kaneo/commit/a56e8cdd66d163365b79f7374ba46d384a676ded))
1010+* **ci:** exclude coverage output from biome checks ([940f00f](https://github.com/usekaneo/kaneo/commit/940f00f34534746f8d3dd23ab4bcdc2e5c22bdd9))
1111+* **ci:** mock email package in integration tests ([77646fc](https://github.com/usekaneo/kaneo/commit/77646fc456044a87731aac6cdddcf985cb636d9d))
1212+* **ci:** use postgres admin db for tests ([be216d6](https://github.com/usekaneo/kaneo/commit/be216d6092f2f8e580bca5a516ad523ec35b6f61))
1313+* **github:** only ignore missing label removals ([399c797](https://github.com/usekaneo/kaneo/commit/399c7977d72326955ed1f149d45c58991c374a2b))
1414+* **github:** preserve zero-valued task numbers ([4f370aa](https://github.com/usekaneo/kaneo/commit/4f370aaca4eb4b339059408ffa78fe1c624f2600))
1515+* **libs:** strip trailing slash before appending /api in resolveApiBaseUrl ([6edf7cf](https://github.com/usekaneo/kaneo/commit/6edf7cfaf1177dfcda2f8924fedb5f6913ec4283))
1616+1717+1818+### Features
1919+2020+* **api:** set userEmail for API key auth and document public routes ([fedd40a](https://github.com/usekaneo/kaneo/commit/fedd40a0657313451042471e1dcd03943b45f2e0))
2121+* **ci:** add api integration scaffolding ([9665488](https://github.com/usekaneo/kaneo/commit/9665488a1d55c080dcd09af56c97a2338ae99e18))
2222+* **ci:** add api project integration harness ([8559555](https://github.com/usekaneo/kaneo/commit/8559555e5542c43c00599c085c07797b2a9e2bc0))
2323+* **ci:** add api task integration tests ([831effd](https://github.com/usekaneo/kaneo/commit/831effdcc9f60d57e2bee6428139dd66272fa9b6))
2424+* **ci:** add api vitest suite ([621c861](https://github.com/usekaneo/kaneo/commit/621c8613dbbb54233af0c8801418aef5cf5b2c7a))
2525+* **ci:** add lint and unit workflow ([d83e642](https://github.com/usekaneo/kaneo/commit/d83e6428129eb388a333e577645dc48fdd134ee3))
2626+* **ci:** disable default api unit coverage and add test:coverage script ([b773513](https://github.com/usekaneo/kaneo/commit/b773513cb89f71ddf7011399e8d81064da274fa8))
2727+* **ci:** extract api app startup ([95b8c47](https://github.com/usekaneo/kaneo/commit/95b8c4730ee840d6bd9ec83f61f9efd921286cb3))
2828+* **test:** add label api integration tests and readme ([528afc3](https://github.com/usekaneo/kaneo/commit/528afc3d16dceb611b7712defc5fb0eb767b23df))
2929+* **test:** add otp email template render smoke test ([ec05672](https://github.com/usekaneo/kaneo/commit/ec05672ac9532133ce19245ce57484c0095b3d26))
3030+* **test:** add vitest config and initial web unit tests ([05fe0fb](https://github.com/usekaneo/kaneo/commit/05fe0fb340cf0e1eafa2352f1c449438ea9109cf))
3131+* **test:** extract resolveApiBaseUrl and add libs unit tests ([2476481](https://github.com/usekaneo/kaneo/commit/2476481f97f6b959cf87d9fb5f5ed4af6fe848bf))
3232+* **web:** move-task popover on task toolbar with readable select labels ([7b747eb](https://github.com/usekaneo/kaneo/commit/7b747eb97b734c6330bc4c3c16164cff069fd0ff))
133## [2.5.1](https://github.com/usekaneo/kaneo/compare/v2.5.0...v2.5.1) (2026-04-01)
234335
+1-1
CLAUDE.md
···229229- **Development Ports**: API runs on 1337, web runs on 5173
230230- **Hot Reload**: Both API and web have watch mode via `pnpm dev`
231231- **CORS**: Configured in API index.ts, controlled by `CORS_ORIGINS` env var
232232-- **No Tests Yet**: Test infrastructure not currently set up in this codebase
232232+- **Testing**: Run `pnpm test` at the repo root (Turbo runs `test` in packages that define it: API unit tests, web unit/component tests, shared packages). API integration tests: `pnpm test:integration` (requires PostgreSQL; env is set in `tests/api-integration/setup.ts`; CI uses `.github/workflows/ci.yml`). Vitest configs: `apps/api/vitest.config.ts` (unit), `apps/api/vitest.integration.config.ts` (integration), `apps/web/vitest.config.ts` (web). Integration tests live under `tests/api-integration/`; API unit tests under `tests/api/`.
233233- **Security**: Never commit secrets, always validate inputs, sanitize outputs
234234235235## Common Patterns
+1-1
CONTRIBUTING.md
···7575git checkout -b feat/cool-new-feature
7676```
77777878-2. **Make your changes** and test them locally
7878+2. **Make your changes** and test them locally (`pnpm test` for unit tests; `pnpm test:integration` for API integration tests with PostgreSQL)
797980803. **Commit using conventional commits**:
8181```bash
···10321032 "projectList": {
10331033 "viewProject": "Voir le projet",
10341034 "shareProject": "Partager le projet",
10351035+ "projectSettings": "Paramètres du projet",
10351036 "linkCopied": "Lien du projet copié dans le presse-papiers",
10361037 "addProject": "Ajouter un projet",
10371038 "deleteConfirmTitle": "Supprimer le projet?",
+1
i18n/mk-MK.json
···10321032 "projectList": {
10331033 "viewProject": "Погледни проект",
10341034 "shareProject": "Сподели проект",
10351035+ "projectSettings": "Поставки на проектот",
10351036 "linkCopied": "Линкот на проектот е копиран во клипборд",
10361037 "addProject": "Додади проект",
10371038 "deleteConfirmTitle": "Избриши проект?",
···11+import { describe, expect, it } from "vitest";
22+import { resolveApiBaseUrl } from "./api-url";
33+44+describe("resolveApiBaseUrl", () => {
55+ it("appends /api when the base has no api suffix", () => {
66+ expect(resolveApiBaseUrl(undefined)).toBe("http://localhost:1337/api");
77+ expect(resolveApiBaseUrl("http://localhost:1337")).toBe(
88+ "http://localhost:1337/api",
99+ );
1010+ });
1111+1212+ it("returns the URL unchanged when it already ends with /api", () => {
1313+ expect(resolveApiBaseUrl("http://localhost:1337/api")).toBe(
1414+ "http://localhost:1337/api",
1515+ );
1616+ });
1717+1818+ it("strips trailing slashes before appending /api", () => {
1919+ expect(resolveApiBaseUrl("http://localhost:1337/")).toBe(
2020+ "http://localhost:1337/api",
2121+ );
2222+ expect(resolveApiBaseUrl("http://localhost:1337/api/")).toBe(
2323+ "http://localhost:1337/api",
2424+ );
2525+ });
2626+});
+9
packages/libs/src/api-url.ts
···11+/**
22+ * Resolves the Hono client base URL from `VITE_API_URL` (or default).
33+ * If the value already ends with `/api`, it is returned as-is; otherwise `/api` is appended.
44+ */
55+export function resolveApiBaseUrl(viteApiUrl: string | undefined): string {
66+ const raw = viteApiUrl || "http://localhost:1337";
77+ const baseUrl = raw.replace(/\/+$/, "");
88+ return baseUrl.endsWith("/api") ? baseUrl : `${baseUrl}/api`;
99+}
···11+# API integration tests
22+33+These tests boot the Hono app with a real PostgreSQL database (see `setup.ts` for env defaults).
44+55+- Run: `pnpm test:integration` from the repo root (requires Postgres and `DATABASE_URL`).
66+- CI: `.github/workflows/ci.yml` starts Postgres and runs the same command.
77+88+Coverage is intentionally incremental: add new files under this directory for additional routes or behaviors, following existing helpers (`helpers/fixtures.ts`, `helpers/database.ts`, `helpers/auth.ts`).