# Required upgrades

Source: https://opvs.ai/docs/guides/vendors/required-upgrades

> Flag a bad version so every install on it moves to your newest version on the next update run, without breaking anyone.

Sometimes a version is not just old but **wrong**, and you want every workspace off it without breaking them. Flag it **must-upgrade**: on the next update run, every install on that version moves to your **newest** version, even installs pinned to that exact version.

## Must-upgrade, revoke, or just publish?

Action

What happens to installs on the old version

Keep working?

Use when

Publish a newer version

`latest` and range pins move on the daily run; exact pins stay

yes

the new one is simply better

**Must-upgrade**

every install moves to your newest version on the next run, whatever its pin

yes, on the fix

the old version is wrong and a safe newer one exists

[Revoke](https://opvs.ai/docs/guides/vendors/revoke-a-version.md)

disabled; calls stop within about a minute

no

running it even briefly is unacceptable, or there is nowhere safe to move to

**Publish the fix first, then flag the bad version.** Must-upgrade needs a newer version to move installs to.

## When to use it

- A correctness bug a newer version fixes: wrong output, a wrong upstream, a silent failure.
- A change every workspace must have: a corrected entitlement, a fixed default, a security hardening.
- An old version you want gone, not just discouraged.

If the new version is just nicer, do not flag anything: `latest` and range pins pick it up anyway, and an exact pin is the workspace's own choice.

## How to flag a version

One call with your partner key:

```bash
# find the version's id
curl -s "https://market.opvs.ai/api/v1/registry/packages/@acme/leads/1.3.0" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])"

# flag it
curl -X POST "https://market.opvs.ai/api/v1/registry/packages/<package_id>/must-upgrade" \
  -H "X-Admin-Key: $OPVS_PARTNER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "1.3.0 drops results when the page is empty; 1.3.1 fixes it"}'
```

`reason` is required (1–1024 characters). It is recorded and shown to workspace admins, so write it for them: what was wrong and which version is safe.

Status

Meaning

`200`

flagged; the reply shows `must_upgrade: true`

`403`

not your package

`404`

no such package version

`409`

that version is already revoked

## What happens next

```
must-upgrade call
  ├─▶ the version is flagged (with your reason and a timestamp)
  ├─▶ a package.must_upgrade webhook goes to subscribed workspaces at once
  └─▶ next update run (daily 03:00 UTC, or when OPVS's API restarts):
        every install on the flagged version → your newest version
        (pins are overridden) → recorded in the workspace's update log
```

- **Pins are overridden.** That is the point: it reaches workspaces that would otherwise stay.
- **It is not instant.** It lands on the next run, not within a minute like revoke.
- **Permissions come along.** If the newest version needs an entitlement the workspace had not granted, a required upgrade grants it and records that in the audit log. Only flag a version when every workspace really must move.

## Tell people anyway

Workspaces are moved off a version they chose, and may gain a permission. Write a `CHANGELOG.md` entry on the new version (what was wrong, why the move is required, what changes for them) and send a direct notice for anything that changes behaviour or permissions.

## Next

[Revoke a version](https://opvs.ai/docs/guides/vendors/revoke-a-version.md).
