# Zurich Kotak — Lead Desk Operator console for the Zurich Kotak "Lead to Policy" demo. Leads arrive through three channels — direct, bancassurance and agency — and run one state machine to policy issuance. **The agents do the work; a person appears at one queue.** Workflow config is seeded from `sm2/custom-apps/zurich-kotak/` (org **84**, app **536**, workflow `zk_wf_lead`). Design doc: `sm2/app-designs/zurich-kotak/design.html`. Workflow spec PDF: `sm2/custom-apps/zurich-kotak/zurich-kotak-workflow.pdf`. ## Run it ```bash npm install npm run dev # http://localhost:5175 npm run build # → dist/ ``` `.env` carries the API host **for local dev only**: ``` VITE_ZINO_API_URL=https://dev.getzino.in ``` Logins (all password `ZurichKotak@2026`, org `84`): | Email | Role | Can do | |---|---|---| | `sanjay.uw@zurichkotak.example` | SME Underwriter | **Clear / Decline Referral** — the only human decision | | `meera.rm@zurichkotak.example` | Bancassurance RM | Submit a **Partner Bank Lead** | | `arjun.posp@zurichkotak.example` | POSP / Broker | Submit a **Partner Agent Lead** | | `kavya.csr@zurichkotak.example` | Direct / Call centre | Submit a **Self-Serve Lead** | | `deepa.ops@zurichkotak.example` | Operations | Cross-channel visibility | Sign in as Sanjay to land in **Referred to Underwriting**, which is where the demo happens. ## How it talks to the platform Everything goes through `src/api/client.js`: - `POST /usr/login` — auth. **`org_id` must be a string**; a number returns `cannot unmarshal number into Go struct field LoginRequest.org_id`. - `POST /app/536/view/recordview` — every queue is one record view (`zk-rv-leads`) filtered server-side on `current_state_name`. - `POST /app/536/view/form-screens` then `POST /app/536/activity` — forms are read from the **live** activity schema and submitted straight back. ### Forms are not defined in this repo Whatever `/view/form-screens` returns is what renders — labels, types, select options, which fields are mandatory. Add a field to an activity in Studio, redeploy, and it appears here with no frontend change. That is deliberate: the workflow is the source of truth, and a hardcoded form would quietly diverge from it. ### Permissions are never enforced here The console does not hide a button to stop someone using it. Every permission decision is the workflow's, made server-side on each submission — the platform refuses and this app reports what it said. Two refusals worth knowing: `/activity` answers **403**, `/start` answers **400**, and both carry `permission denied`. ### The runtime-config contract `VITE_ZINO_API_URL` is read at **runtime** from a `config.js` the server writes when it places the build — never compiled in. One artifact is promoted between environments unchanged, so a build-time URL would point every environment at whichever backend happened to build it. `requireConfigValue` throws if it is missing, so a production build with no `config.js` fails loudly rather than calling the wrong backend. `vite.config.js` uses `base: './'` and the router takes its basename from the `` the server writes, so **one build serves any mount path**. Do not reintroduce a build-time base. **This is also why the fonts and logo live under `src/assets/` and not `public/`.** Vite rewrites bundled asset URLs to be relative; a `public/` file referenced as `/fonts/…` stays absolute and 404s under the `/zurich-kotak/` mount path. The favicon is the one exception — it stays in `public/brand/` and is referenced relatively from `index.html`. ## Deployment Registered with frontgen by `sm2/custom-apps/zurich-kotak/05_frontgen_project.sql` (slug `zurich-kotak`, repo_name `zurich_kotak`, org 84). A push to `main` builds and serves at **https://preview-dev.getzino.in/zurich-kotak/**. The webhook only fires on a **new** push — a push made before the frontgen project row existed matched no project and did nothing. ## State of the build | Piece | Status | |---|---| | Brand — Zurich Sans, palette, logo | done (kept from the original scaffold) | | Sign-in against the real gateway | done | | Runtime config, relative base, router | done | | Pipeline sidebar (mirrors `tbl_wf_states`) | done | | Queue lists | waiting on the `zk-rv-leads` record view | | Lead file, activity forms, attribution panel | waiting on `zk-dv-lead` + form screens |