# Prompt for the vt-api agent — auto-approve products of approved producers

> Paste everything below the line into the Claude session working on `vt-api`.

---

You are working on **vt-api**, the Node.js + Express + MongoDB backend of **Viață la Țară**. The Flutter
client follows `FLUTTER_ALIGNMENT.md` as the contract. This task adds one moderation feature behind a
switch an admin can turn on and off at runtime. Read the whole brief before changing anything.

## 1. Goal

Today every product a business creates starts as `pending` and needs an admin's approval, even when the
producer (the shop) is already approved. We want an **admin-controlled feature flag**:

- **Flag ON:** a product created by a producer whose status is `approved` is stored as **`approved`**
  straight away and is public immediately.
- **Flag OFF:** today's behaviour — every new product is `pending`.

The flag is global, stored in the database (not an env var), so admins can flip it from the app
without a deploy. It must be possible to exclude individual producers.

## 2. Contract rules — do not break these

- Envelope on every response: `{ "data": …, "error": null }` / `{ "data": null, "error": { code, message, details? } }`.
- `error.message` is shown to users verbatim — Romanian, addressed to the user.
- **Additive changes only.** Every existing field, endpoint and default stays as it is. With the flag
  OFF (the default), behaviour must be byte-for-byte what it is today.
- Public endpoints keep returning only `approved` items.

## 3. Data

### 3.1 App settings (new, single document)

Collection `settings` (or equivalent), one document:

```jsonc
{
  "autoApproveProducts": false,          // default false
  "updatedAt": "…", "updatedBy": "<adminUserId>"
}
```

Create it lazily with the defaults if it doesn't exist. Cache it in memory if you like, but a `PATCH`
must take effect for the very next request (invalidate the cache on write; multiple instances, if any,
must not serve a stale value for more than a few seconds).

### 3.2 Producer (additive field)

```jsonc
"autoApproveProducts": true    // default true; false = this producer's products always need review
```

Returned only on owner/admin responses (`/shop/producer`, `/admin/producers*`), like `moderationNote`.
Never on public responses.

### 3.3 Product (additive field)

```jsonc
"autoApproved": true           // true when the server approved it without an admin; absent/false otherwise
```

Owner/admin responses only. It lets admins audit what went live unreviewed.

## 4. Rules

On `POST /shop/products` (and `POST /admin/…` paths that create products on a producer's behalf, if any):

```
status = (settings.autoApproveProducts
          && producer.status == "approved"
          && producer.autoApproveProducts != false)
         ? "approved"   (and set autoApproved = true)
         : "pending"
```

- `producer.verified` does **not** matter — the producer's `status` does.
- Everything else about product creation (validation, 201, response shape) is unchanged.
- **Edits** (`PUT /shop/products/:id`) keep today's rule: they don't change the status. In particular an
  owner editing a `rejected` or `requestInfo` product does **not** auto-approve it — only an admin can.
- Turning the flag **off** does not touch existing products; it only affects products created afterwards.
- An admin can still `reject` / `request-info` an auto-approved product with the existing endpoints. A
  rejection clears `autoApproved`. A manual `approve` sets it to `false`.
- If the producer is later rejected, the rule simply stops applying to its new products (its status is no
  longer `approved`).

## 5. Endpoints

| Method & path | Auth | Body | Success `data` | Errors |
|---|---|---|---|---|
| `GET /admin/settings` | admin | — | `{ "autoApproveProducts": bool, "updatedAt", "updatedBy" }` | 403 |
| `PATCH /admin/settings` | admin | `{ "autoApproveProducts": bool }` (any subset of known keys) | same as GET | 403 · 422 `body.autoApproveProducts` not a boolean · 422 unknown key |
| `PATCH /admin/producers/:id/auto-approve` | admin | `{ "enabled": bool }` | Producer (with `autoApproveProducts`) | 404 `Producătorul nu a fost găsit.` · 422 |
| `GET /admin/products` | admin | new optional query `autoApproved=true\|false` | paginated Product | — |
| `GET /config` | none | — | `{ "autoApproveProducts": bool }` | — |

`GET /config` is public and cacheable for 60 s (`Cache-Control: public, max-age=60`). The app uses it to
tell a business user, before they submit, whether the product will go live immediately. It exposes only
this boolean.

Validation messages (Romanian): `Valoarea trebuie să fie adevărat sau fals.` for a non-boolean.

## 6. Tests to add

1. Flag OFF (default): approved producer creates a product → `pending`, no `autoApproved`.
2. Flag ON, producer `approved` → `approved`, `autoApproved: true`, appears in `GET /products`.
3. Flag ON, producer `pending` / `rejected` → `pending`.
4. Flag ON, producer `autoApproveProducts: false` → `pending`.
5. Flag ON, owner edits a `rejected` product → stays `rejected`.
6. Flip the flag ON → OFF: existing auto-approved products stay `approved`; the next one is `pending`.
7. Admin rejects an auto-approved product → `rejected`, `autoApproved` cleared, hidden publicly.
8. Non-admin → 403 on `/admin/settings` and `/admin/producers/:id/auto-approve`.
9. `PATCH /admin/settings` with `"yes"` → 422 on `body.autoApproveProducts`; unknown key → 422.
10. `GET /config` without a token → `{ autoApproveProducts }` only.

## 7. Documentation

Update `FLUTTER_ALIGNMENT.md`:

- §3 (moderation): the auto-approve rule.
- §4.3 Product: `autoApproved` (owner/admin only). §4.4 Producer: `autoApproveProducts` (owner/admin only).
- §5: the new endpoints and the `autoApproved` filter.
- §9 changelog row and a §10 checklist line for the app.

## 8. Report back

Reply with: the exact response shapes you shipped, the default values, anything you changed from this
brief and why, and the test results.
