# AGENTS.md

Entry point for **any AI agent** (Claude, GPT, Cursor, etc.) working on this repo.

This is a working copy of the Bina Plus codebase used as a sandbox for V4 development. The original codebase lives in a separate GitHub repo. **Read this whole file before making changes** — there are non-obvious git remotes, branches, and feature-isolation conventions you must respect.

---

## ⚠️ HARD RULES (read first)

1. **GIT — never push to `origin`.** `origin` points to the *original* Bina Plus repo (`israel25569/bina_plus`) which is owned by upstream and deploys to production at `binaplus.co.il`. We push **only** to the `v4` remote (`israel25569/binaplusV4`). If you accidentally type `git push` without an explicit remote, that's `origin` — wrong. Always: `git push v4 <branch>`.
2. **DEPLOYMENT — staging is `https://idev.binaplus.co.il`.** It's served by *this very machine* (NPM proxy in front of local Nest on 1813 + local Vue on 1814). When you save a file, the dev servers auto-reload and the change is live on `idev` within seconds. There is no separate "deploy" step. See `DEPLOYMENT.md`.
3. **USERS — closed beta + debug panel are env-driven, no schema changes.**
   - `BETA_USERS_WHITELIST` (in `backend/.env.stg`) is the only list of emails that can log in to staging.
   - `DEBUG_USERS_EMAILS` (same env file) is the list of emails that see the live debug panel.
   - Adding/removing a user = edit the env + restart backend. Don't add a `featureFlags` field to the User schema (would complicate the eventual upstream migration).
4. **MONGO — local only.** Backend connects to `mongodb://localhost:27017` / db `binaplus-local`. Never connect to Atlas from this workspace, except via the read-only `mongodump` flow documented in `LOCAL_DEV_SETUP.md`.

---

## TL;DR

- The whole V4 sandbox lives under **`/home/user/bina_plus_workspace/`** with two subfolders:
  - **`main/`** — the V4 trunk worktree (where you work day-to-day).
  - **`branches/<name>/`** — isolated feature-branch worktrees off `origin/main`.
- The older `/home/user/bina_plus/` workspace still exists but is **read-only / unused** — don't work there.
- Two git remotes: `origin` (the **original** project — read-mostly, never push) and `v4` (**ours** — push freely).
- Local stack runs on ports **1813** (backend) / **1814** (frontend) / **1815** (admin) against a **local MongoDB** named `binaplus-local`.
- Public staging URL: **`https://idev.binaplus.co.il`** — auto-deploys from this machine when you save a file.

---

## 1. Repo layout

| Path | Stack | Port | Notes |
|------|-------|------|-------|
| `backend/` | NestJS 10 + Mongoose + TypeScript | **1813** | REST `/api/*` + Socket.IO. Watch mode via `npm run start:dev`. |
| `frontend_v3/` | Vue 3 + Vuex 4 + Vue CLI 5 | **1814** | Main client app. Web + Cordova (Android/iOS). Default landing is `/unified-chat`. |
| `admin_frontend/` | Vue 3 + Vite 7 | **1815** | Admin dashboard. Requires Node 20+ (`/usr/local/n/versions/node/20.19.6/bin`). |
| `frontend/` | Angular 17 + NgRx | — | **Legacy.** Being migrated to Vue 3. Don't add features here. |

Detailed setup, ports, env values, DB collections, API keys: see [`LOCAL_DEV_SETUP.md`](./LOCAL_DEV_SETUP.md).

Deep architecture (auth, streaming SSE, image flow, admin panels, file cheat-sheet): see [`SYSTEM_DOCUMENTATION.md`](./SYSTEM_DOCUMENTATION.md).

Recent V4 work + open items: see [`SESSION_NOTES.md`](./SESSION_NOTES.md).

Production / staging deployment: see [`DEPLOYMENT.md`](./DEPLOYMENT.md).

---

## 2. Two git remotes — the most important convention

```
origin → git@github.com:israel25569/bina_plus.git       # ORIGINAL — touch with care
v4     → git@github.com:israel25569/binaplusV4.git      # OURS    — push freely
```

- **`origin`** is the original (existing, deployed) project. Treat it as upstream. We pull from it; we **do not push to it casually**. PRs to `origin/dev` happen only when a feature is ready and the user explicitly says so.
- **`v4`** is our fork / development repo. The local `main` tracks `v4/main`. Push V4 work here freely.
- The original project's branches: `dev` (active), `stg` (staging), `main` (prod). **Their** flow is `dev → stg → main`. Our `main` is a divergent fork that lives on `v4` only.
- When in doubt: `git push v4 <branch>` is safe; `git push origin <branch>` is not.

---

## 3. Feature branch / worktree convention

Every isolatable feature lives in its **own worktree branch** based on `origin/main`, so it can be reviewed, cherry-picked into the original repo, or reverted independently of other work.

```
/home/user/bina_plus_workspace/main/                       → main          (V4 trunk, has everything)
/home/user/bina_plus_workspace/branches/debug-panel   → feature/debug-panel    (only debug stuff)
/home/user/bina_plus_workspace/branches/unified-chat  → feature/unified-chat   (only unified-chat stuff)
```

Each `feature/*` branch contains **only the diff for that feature**, applied on top of clean `origin/main`. They are pushed to `v4` for backup, never to `origin` unless explicitly opening a PR.

To create a new feature branch:
```bash
cd /home/user/bina_plus_workspace/main
git worktree add -b feature/<name> /home/user/bina_plus_workspace/branches/<name> origin/main
# do work in the new dir, then:
cd /home/user/bina_plus_workspace/branches/<name>
git push -u v4 feature/<name>
```

To verify a feature is isolated:
```bash
git diff origin/main feature/<name>     # should show ONLY that feature's files
```

To revert a feature: just don't merge / cherry-pick that branch.

---

## 4. Common commands

### Backend
```bash
cd backend
npm run start:dev              # NODE_ENV=stg, watch mode, port 1813
npm run build                  # nest build
npm run lint                   # ESLint --fix
npm test                       # jest
```

### Frontend V3
```bash
cd frontend_v3
npm run serve                  # dev server, port 1814
npm run build:staging          # staging build
npm run build:production       # prod build
npm run lint
```

### Admin (Node 20+)
```bash
cd admin_frontend
PATH=/usr/local/n/versions/node/20.19.6/bin:$PATH npm run dev   # port 1815
```

### Logs
- Backend: `/tmp/v2_backend.log`
- Frontend: `/tmp/v2_frontend.log`
- Admin: `/tmp/v2_admin.log`

---

## 5. Backend conventions (must-know)

- **API prefix:** `/api`. All controllers register under it.
- **Response shape:** Every endpoint is wrapped by `TransformInterceptor` → `{ success, statusCode, message, data }`. Never return raw objects.
- **Auth:** JWT via Passport (`JwtAuthGuard`) + role-based access (`RolesGuard` + `@Roles(USER_ROLE.user | admin | super_admin)`). 401 on the frontend triggers automatic logout.
- **Validation:** `ValidationPipe` is global — every DTO validated, payload trimmed.
- **AI providers:** Abstracted in `backend/src/shared/`. Supports OpenAI, Claude, Gemini, OpenRouter, Stability.AI, Replicate.
- **Streaming:** SSE-style chunks via `res.write(...)` + `BINA_STREAM_RESPONSE_DIVIDER` markers. The classic chat consumer (`ChatDetailsWrapper.handleStreamResponse`) is the reference implementation for char-by-char typing animation. **Never break the streaming format without updating both producer and consumer.**
- **Migrations:** files under `backend/src/modules/migration/migrations/migration_v{N}.ts`. **Never modify existing files.** **Never bump `CURRENT_MIGRATION_VERSION`** — the user does that manually.

---

## 6. Frontend conventions (Vue 3, frontend_v3)

- **Vuex store** keys: `user`, `authToken`, `lang`, `aiModels`, `appConfig`. Most code reads via `this.$store.state.user`.
- **Globals:** `globalMixin.js` (~1163 lines) is mixed into every component — provides `is_mobile()`, `isRTL`, formatting helpers, `isNull`, `$bus` (event bus). Don't reinvent these.
- **i18n:** Hebrew (`HB`) + English (`EN`) via `langs.js`. RTL is the default. Use `this.isRTL` everywhere user-facing strings change direction.
- **API:** `services/api.js` axios singleton. Domain services (`chatService.js`, `imageService.js`, `quickTilesService.js`, `appConfigService.js`, `socketService.js`) build on top.
- **Streaming consumption:** `chatService.processStreamData(rawChunk)` returns `{ id, actualData, reasoning, done, error }` — the canonical SSE parser. Use it for any chat stream reader.
- **Reactivity gotcha:** when you `messages.push(rawObj)` then call a function with `rawObj`, the function gets the **raw** reference and mutations on it will **not** trigger re-renders. Always re-read from the array: `const reactive = this.messages[this.messages.length - 1]`.

---

## 7. Local infrastructure

- **MongoDB:** local `mongod` (systemd) on port 27017. Database: `binaplus-local`. Has 18 of the production collections imported (filtered, no chat/image histories — saved 707 MB). Backend connects via `mongodb://localhost:27017`.
- **Production DB (`bina-plus-main` on Atlas):** access only via the read-only Atlas user `israel-readonly`. Used to refresh local data via `mongodump`. **We never `mongorestore` back to Atlas.** See `LOCAL_DEV_SETUP.md` § "How to refresh the local DB".
- **API keys:** all in `backend/.env.stg`. They are **real, billable** staging keys copied from upstream. Replace with sandbox keys before heavy testing.

---

## 8. Working with the user — ground rules

- **Hebrew-first.** The user types in Hebrew. UI strings must work in RTL. Default `lang === 'HB'`.
- **Local mongo only.** Never connect to Atlas from this workspace, even read-only, except via the documented `mongodump` flow.
- **Never push to `origin`** without explicit permission. `v4` is fine.
- **Streaming behavior is sensitive.** The 175ms-per-word backend delay is **intentional** (paces SafeMode filter checks). Don't reduce it without asking.
- **Beta access whitelist** (`BETA_USERS_WHITELIST` in `backend/.env.stg`) — the deployed staging site only lets specific emails in. Adding a new tester = update env + restart backend.
- **Debug panel whitelist** (`DEBUG_USERS_EMAILS`) — only those emails see the live debug panel. See `feature/debug-panel` branch and `SESSION_NOTES.md`.

---

## 9. Adding a user-gated ("show to specific users only") feature

Default convention for any feature that should ship to production but only be **visible to specific users at first** (early access, internal testing, debug tools, hidden pages, etc.). Built on top of the same pattern the debug panel uses — env var driven, no schema changes.

**Why this pattern (and not a `featureFlags` array on the User document):** keeping `User` clean is critical because V4 features eventually get migrated back into the upstream `bina_plus` repo. Adding a field to the User schema means a DB migration plus possible conflict with upstream changes. An env-var gate has zero schema footprint and is trivial to remove (delete the env, delete the check) when the feature is ready for general release.

**Tradeoff to know:** adding/removing a user requires a backend restart (it's an env var). Fine for ≤ ~10 testers; if a feature ever needs >50 testers we'll graduate to a DB-backed mechanism.

**Steps to gate a new feature called `docs` (use this as a template):**

1. **Backend env** — `backend/.env.stg`:
   ```ini
   DOCS_USERS_EMAILS=info@odma.co.il,israel25@enativ.com
   ```

2. **Backend `app-config.service.ts`** — compute the flag from env and add it to the user object returned to the frontend. Mirror the `isDebugUser` pattern already in the file. Net diff: ~3 lines.

3. **Backend controller(s)** — guard each endpoint. Either inline:
   ```ts
   if (!user?.email || !this.docsWhitelist.includes(user.email.toLowerCase())) {
     throw new NotFoundException();   // 404, not 403 — feature is meant to be invisible
   }
   ```
   …or copy the pattern of `DebugEventsService.isDebugUser` into a small `DocsAccessService` if it gets reused.

4. **Frontend** — guard the route + UI:
   ```vue
   <router-link v-if="$store.state.user?.isDocsUser" to="/docs">מסמכים</router-link>
   ```
   For the route itself, add a `meta: { requiresDocs: true }` and check it in the existing `router.beforeEach` (next to the `requiresAuth` check) — redirect non-flagged users to `/`.

5. **Document it** — add a one-liner to `SESSION_NOTES.md` § "Major features added in V4" so the next agent knows the feature exists and how it's gated.

**When the feature is ready for general release:** delete the env var, delete the `isDocsUser` computation in `app-config.service.ts`, delete the `v-if` and route guard. The feature becomes visible to all users with no DB cleanup needed.

**Reference implementation:** the live debug panel — see `SESSION_NOTES.md` § "Live Debug Panel" and the `feature/debug-panel` branch under `/home/user/bina_plus_workspace/branches/`. The same five steps were followed there end-to-end.

---

## 10. Where to look first when…

| Task | Start with |
|------|-----------|
| Adding a backend endpoint | `SYSTEM_DOCUMENTATION.md` § 4 (API reference), copy a sibling controller pattern |
| Touching chat streaming | `SYSTEM_DOCUMENTATION.md` § 6 + `chatService.js` + `chat-history-stream.service.ts` |
| Touching image generation | `SYSTEM_DOCUMENTATION.md` § 7 + `generate-image.service.ts` |
| Adding a Unified Chat capability tile | `quick-tiles` backend module + admin panel + `quickTilesService.js` |
| Adding a feature gated to specific users (early access, hidden) | `AGENTS.md` § 9 — env var pattern (no schema changes) |
| Adding a new beta user | `backend/.env.stg` `BETA_USERS_WHITELIST` + restart backend |
| Adding a debug-panel user | `backend/.env.stg` `DEBUG_USERS_EMAILS` + restart backend |
| Deploying changes to staging | `DEPLOYMENT.md` § "Staging" |
| Resuming an unfinished thread | `SESSION_NOTES.md` § "Open items" |
