> ## Documentation Index
> Fetch the complete documentation index at: https://docs.virusstudio.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release notes for vrs_permanentid. New entries are added at the top with each update.

All notable changes to `vrs_permanentid` are documented here. The most recent release is at the top.

<Update label="v1.2.0" description="2026-08-08">
  Permanent IDs now belong to the **player**, not the character, and they finally show up where staff actually work: in admin commands and in txAdmin.

  <Note>
    **Upgrading from 1.0.0?** The database migrates itself on first start. Back up first, see [Installation](/permanent-id/installation#migration-and-upgrades-v1-0-0-v1-1-0).
  </Note>

  ### ⚠️ Breaking changes

  * **One ID per account, not per character.** IDs are now keyed on the player's `license` instead of their `citizenid`. A player with three characters used to own three IDs; now they own one.
  * **IDs now start at 1000** (`Config.StartId`), up from `1`. This keeps them clear of live server IDs so both can be typed into the same commands without ambiguity. Only affects brand-new installs, existing IDs are never renumbered.
  * **Server exports are online-only and never yield.** `GetPermanentIdByIdentifier` and `GetIdentifierByPermanentId` used to fall back to a database lookup, which could crash the *calling* resource with *"attempt to yield across C-call boundary"*, an export cannot yield across a resource boundary. Query the `vrs_permanent_ids` table directly if you need offline lookups.
  * **`/id` is now owned by this resource.** QBox/QBCore register their own `/id` that prints the slot number; left alone, both fire on one chat message. The patch to disable theirs is in `patches/`.

  ### Added

  * **Automatic database migration** from the 1.0.0 layout. Detects the old schema, keeps each player's **oldest** ID, merges their other character rows into it, and moves the unique key from `identifier` to `license`. If the migration cannot complete, the resource **refuses to assign any ID** rather than risk handing every player the same row.
  * **`patches/`**, drop-in patches that teach admin commands the permanent ID without editing those commands one by one:
    * `ox_lib`, the `playerId` argument parser. One file, \~30 commands (`/giveitem`, `/givemoney`, `/setjob`, `/revive`, `/givekeys`, ...).
    * `qbx_core`, `qb-core`, `es_extended`, the framework `GetPlayer` lookups, for commands that take the id as a plain number.
    * `monitor`, txAdmin (see below).
    * Every patch is **statebag-based**, so it carries no dependency on this resource, has no load-order requirement, and does nothing at all when `vrs_permanentid` is stopped.
  * **txAdmin support**, in three places:
    * permanent-ID lines in the **live console**, no patch needed;
    * the ID appended to the player name in the **web panel** and the **in-game menu** (`monitor/resource/sv_playerlist.lua`);
    * the ID in the panel's **sidebar badge** in place of the slot number (`monitor/panel/patch-panel.js`). Display only, clicking a player, kicking, banning and spectating still use the real slot number.
  * **`Config.MinPid`**, the number below which a value is always read as a server ID. Published as the `vrs_pid_min` convar so the patches can read it without depending on this resource.
  * **`Config.Console`**, toggles the permanent-ID lines printed on connect, character load and disconnect.
  * **`GetPermanentIdByLicense(license)`** and **`GetIdentifierBySource(source)`** exports.
  * [**Installation guide**](/permanent-id/installation), plain-language setup, and a rewritten `patches/README.md`.

  ### Changed

  * IDs are assigned during **`playerConnecting`** instead of on character load. They have to exist before the player takes a slot, because txAdmin captures a player's display name exactly once, at `playerJoining`, and never updates it afterwards. A character-keyed ID arrives far too late for that.
  * `OnPlayerLoaded` no longer assigns anything. It records which character is in play and publishes the character name.
  * The statebag is re-asserted on character load, since the client is not necessarily connected yet when `playerJoining` sets it.
  * `/pid` now works on any connected player, not only ones with a character loaded.
  * `/findpid` reports the account **license** instead of a citizenid.
  * Resource restart with players already online now re-adopts them.

  ### Fixed

  * **`Duplicate entry '…' for key 'identifier'`** on character load after upgrading. `CREATE TABLE IF NOT EXISTS` cannot alter an existing table, so the 1.0.0 unique index on `identifier` survived the upgrade untouched. Made worse on a non-strict `sql_mode`, where MySQL silently accepted an empty `identifier` instead of raising an error, quietly creating junk rows. Now handled by the migration.
  * The temporary source used during `playerConnecting` is no longer written into the source-keyed lookup tables, it can differ from the ID the player ends up with, which left stale entries behind.
  * A failed migration no longer leaves connecting players waiting forever on an internal "ready" flag.

  ### Notes for people who patch txAdmin

  `monitor` is part of **FXServer**, not your server folder, so both txAdmin patches are erased by every artifacts update. Stock copies are saved alongside each patched file as `.stock.bak`.

  After re-applying the panel patch you must restart the **txAdmin process itself**, restarting the server is not enough, because txAdmin loads the whole panel into memory once at startup. Then hard-refresh your browser (`Ctrl+Shift+R`): the file keeps its name, so nothing else tells the browser it changed.
</Update>

<Update label="v1.0.0" description="Initial release">
  ### Added

  * Permanent, per-character numeric IDs assigned on first login and stored in `vrs_permanent_ids`.
  * Zero-config install. Table auto-created, no SQL file required.
  * Framework auto-detection via [vrs\_bridge](/getting-started/submitting-a-request) (QBox, QBCore, ESX).
  * Server-authoritative ID assignment via MySQL `AUTO_INCREMENT`.
  * Replicated statebags: `Player(src).state.vrs_pid` and `Player(src).state.vrs_pid_name`.
  * Commands: `/id`, `/pid`, `/findpid`, `/showids`. All renameable / disableable in `config.lua`.
  * Server exports: `GetPermanentId`, `GetPermanentIdByIdentifier`, `GetIdentifierByPermanentId`, `GetSourceByPermanentId`, `GetAllOnline`.
  * Client export: `GetMyPermanentId`.
  * ACE permission support (`vrs.permanentid`), with QBox/QBCore `admin`/`god` and ESX `admin` groups passing automatically.
  * Open `locales/*.lua` for translations with English fallback.
  * Escrow-open `config.lua` and `locales/*.lua`.
</Update>
