--- module: claims.vendors title: Vendors tab: Claude order: 40 audience: dev --- > Act-without-guessing reference. All items code-confirmed in hiveops-claims (2026-07-01) unless marked (unverified). ## Ownership - **Service:** hiveops-claims (`hiveiq-claims`, port 8092). Owns vendor read + write end to end. - **Frontend:** `hiveiq-claims-frontend`, `claims.bcos.cloud`, port 5179. Page: `frontend/src/components/Vendors/VendorsPage.svelte`; create panel: `components/modals/AddVendorModal.svelte`; api: `lib/api.ts` → `vendorAPI`. - No other service, no Kafka, no cross-service call in this feature. ## Endpoints (exact) | METHOD | Path | Notes | |--------|------|-------| | GET | `/api/claims/vendors` | optional `?type=CIT` or `?type=SP` (binds `Vendor.VendorType`); no type → all | | POST | `/api/claims/vendors` | body `{name*, type*, contactName?, contactEmail?, contactPhone?}`; returns `201` | - External route: `https://api.bcos.cloud/claims/api/claims/vendors`. - Auth: `Authorization: Bearer ` required. Scope key = JWT `institutionKey` claim. - Required fields: `name` (`@NotBlank`), `type` (`@NotNull`, `CIT`|`SP`). Email validated **client-side only**. - Response fields: `uuid, name, type, contactName, contactEmail, contactPhone, createdAt`. ## Storage - **DB:** `hiveiq_claims` (Postgres, `10.10.10.188` via ProxyJump). **Table:** `vendors`. - Columns: `id, uuid, name, type('CIT'|'SP'), contact_name, contact_email, contact_phone, institution_key(nullable, no index), created_at, updated_at`. - FK in: `claims.cit_vendor_id`, `claims.sp_vendor_id` → `vendors(id)`. - **Kafka topics:** none for this feature. ## Gotchas - **No update / no delete endpoint** — `VendorController` has only GET + POST. Typos are fixable only via direct SQL `UPDATE vendors`. - **No role gate** — `SecurityConfig` = `anyRequest().authenticated()`. Do NOT assume `hasAnyRole('MSP_ADMIN','BCOS_ADMIN')`; isolation is `institutionKey` only. - **No dedup** — `(institution_key, name)` is not unique; POST twice = two rows. - **Blank `institutionKey` JWT** pools vendors under a null key (nullable column) → apparent "missing" or cross-user leakage. - Frontend splits CIT/SP **client-side**; `typeFilter` in `VendorsPage` is declared but not bound to any UI control, so `?type=` is currently unused. - Deleting a vendor referenced by a claim fails the FK — unassign on the claim first. - `dev` profile = H2 (`create-drop`, Flyway off); `prod` = Postgres + Flyway `validate`. ## Do NOT - Do NOT tell users to edit or delete a vendor in the UI — no such action exists. - Do NOT claim vendor changes emit Kafka events — they don't. - Do NOT invent an MSP/all-institutions vendor view — every query is `institutionKey`-scoped. - Do NOT expect a role/permission error path — auth failures are 401 (missing/invalid token), not 403 by role. - Do NOT run `docker exec hiveiq-postgres` on the services VM — Postgres is on `10.10.10.188`. - Do NOT reference this AI assistant as anything but "Adoons" externally. ## Cross-links [claims.vendors] Overview · Internal · Architect. Service facts: [technical.claims]. Platform: [platform.service-ownership], [platform.kafka], [platform.data-architecture].