# CLAUDE.md — smartbotic-vectorapi C++20 REST API fronting `smartbotic-database` (gRPC) for n8n + other clients. Stores RAG vectors + JSON, organized into **projects** with **multi-key per-project-grant auth**. React admin UI. Ships as Debian `.deb`s. ## Build / test / run ```bash # Backend + web UI (Release) cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_WEBUI=ON -S . cmake --build build -j"$(nproc)" # Tests (GoogleTest). Integration tests need a running smartbotic-database on localhost:9004; # they GTEST_SKIP() cleanly if it's unreachable. BUILD_WEBUI=OFF to skip the npm build during test cycles. cmake -B build -G Ninja -DBUILD_TESTS=ON -DBUILD_WEBUI=OFF -S . && cmake --build build -j"$(nproc)" ctest --test-dir build --output-on-failure # Run locally (use the repo's api/ for /openapi.json,/llms.txt,/docs and the built UI) SMARTBOTIC_VECTORAPI_KEY=dev ./build/src/smartbotic-vectorapi \ --config config/config.json --share-dir "$PWD/api" --webui-dir "$PWD/build/webui/dist" # Web UI only cd webui && npm install && npm run build # → webui/dist ; `npm run dev` for the :3000 proxy dev server ``` ## Architecture (where things live) - `src/` — the server. `vectorapi_core` static lib + `main.cpp`. Namespace `svapi`. Flat headers, quoted includes. - `db_gateway` (`qualify(project,coll)` + `DbGateway` over `smartbotic::database::Client`), `settings_store` (global settings, hot-reload), `key_store` (API keys, hot-reload, bootstrap admin key), `collection_registry` (per-project metadata), `embeddings` (OpenAI), `auth` (sessions, bearer/cookie), `server` (ApiServer + auth helpers), `handlers/*` (one file per route group). - Auth model: pre-routing **authenticates** `/api/*` (401); each handler **authorizes** via `requireKey` → `requireAdmin` / `requireProjectAccess` (403). Keys are referenced by a stable **`id`** (not the secret). - `webui/` — React 19 + Vite + TS (strict, `erasableSyntaxOnly`) + Tailwind + Monaco. Cookie-session auth (`credentials:'include'`). Pages read `currentProject`/`admin` from `useAuthStore`; all calls go through `src/api/client.ts`. - `api/` — `openapi.json` (3.1), `llms.txt` (llmstxt.org), `docs/` (Redoc page). Served at `/openapi.json`, `/llms.txt`, `/docs`. Shipped in the server `.deb`. **Keep these in sync when changing routes.** - `packaging/` — `build.sh` (`--local` + Docker trixie), `deb/create-debs.sh`, control templates, systemd unit, maintainer scripts. `docs/superpowers/` — design spec (esp. **Addendum A**) + the 3 implementation plans. ## Conventions - C++20, `nlohmann/json`, `spdlog`, cpp-httplib (FetchContent, OpenSSL on). Handlers `throw svapi::ApiError`; a global exception handler maps to `{error:{code,message}}` + HTTP status (`errors.hpp`: 400/401/403/404/422/503/500). - Filters: `field:op:value` (`op` ∈ eq/ne/gt/gte/lt/lte/in/contains/exists/regex/search). - TS: no `any`, no TS `enum`, no constructor parameter-property shorthand (tsconfig `erasableSyntaxOnly`). Iterating parsed JSON: bind to a named var first (range-for over `nlohmann::json::parse(...)[...]` dangles). - Commits: conventional prefixes (`feat`/`fix`/`build`/`docs`/`test`). Branch for feature work; `main` is pushed to `ssh://git.smartbotics.ai:10022/fszontagh/smartbotic-vectorapi.git`. ## Data model & runtime config - Bootstrap `config.json` is minimal: `log_level`, `http.{bind_address,port}`, `database.address`. Everything else lives in the DB and **hot-reloads** (subscribe + atomic snapshot swap). - Global service collections (DB `default` project, **no leading underscore** — see gotcha): `vectorapi_keys`, `vectorapi_settings`. Per-project registry: `:vectorapi_collections`. The `vectorapi_` prefix is reserved (collection-create rejects `_` and `vectorapi_`). - First run with no keys generates an admin key (`projects:["*"], admin:true`) and logs it once; `SMARTBOTIC_VECTORAPI_KEY` seeds it, `OPENAI_API_KEY` seeds embeddings. ## ⚠️ Gotchas (hard-won — don't relearn these) - **DB v2.3.1: `_`-prefixed collections misroute when project-qualified.** Writes land in MemoryStore (mirror skips `_`-names) but reads of `default:_foo` route to LMDB → null. → service collections use **no leading underscore** (`vectorapi_*`). Suspected DB bug. - **DB v2.3.1: `dropProject` does not physically purge collection data.** A recycled project name is otherwise blocked by stale collections/registry → the project-delete handler drops the registry + collections first, and collection-create drops invisible orphans (after the registry "exists" check). - **DB client strips an `id` field from stored doc bodies.** So API keys store their stable id as `key_id` in the body (exposed as `id` externally); document handlers strip `id` before insert and use the separate id param. - **Debian 13 (trixie) gRPC cmake config is broken** unless `protobuf-compiler-grpc` + `libgrpc++-dev` + `libprotobuf-dev` are installed — `find_package(gRPC CONFIG)` (used transitively by `smartbotic-db-clientConfig.cmake`) fails on a `gRPCTargets.cmake` referencing missing plugin files. The Docker base installs them. - **Abseil ABI:** `smartbotic-database`/client debs must be built against the system's current Abseil; a stale build crash-loops on `libabsl_*.so.`. Rebuild the DB if it won't start. - **Monaco** is bundled locally (`webui/src/monacoSetup.ts`) so the editor works offline — do not revert to the CDN loader. - systemd unit is `Type=notify`; the binary must be built with `libsystemd` (it is, when `libsystemd-dev` is present) or change to `Type=exec`. ## Deploy / publish ```bash ./packaging/build.sh # Debian-13 .debs → dist/debian13/ ./packaging/build.sh --repo --suite trixie --sync # + publish to repository.smartbotics.ai (outward-facing!) ``` Publishing uploads to the live apt repo — only with explicit confirmation. The deb-repo tooling is `/data/smartbotics-deb-repo/scripts/`.