Releases: jamesmblakely/IdentityBridge
Releases · jamesmblakely/IdentityBridge
Release list
IdentityBridge 1.0.0
First public release.
Features
- Login continuity: while the server is in offline mode, known returning Java players are
restored to their real online UUID at pre-login (via Paper'screateProfileExactprofile API),
so they keep inventory, location, stats, advancements, and other UUID-keyed progress. Only
genuine offline-style logins are rewritten — proxy/forwarded UUIDs are left untouched. - Known-player learning: authenticated online-mode logins are recorded (name → online UUID,
last IP, timestamps), with careful name-capitalisation handling. - Temporary offline identities: unknown players seen during an outage are recorded for later
migration (or can be blocked instead). - Safe data migration:
/idb migrateand/idb migrate-uuidmove UUID-keyed data to the
correct online UUID — dry-run by default, with backups, missing-source reporting, an extensible
file-location list, and a hard stop if the source or target player is currently online. - Lossless conflict resolution: when both UUIDs already hold data, migration unifies the two
profiles instead of skipping or clobbering —statscounters are summed,advancementsare
unioned (earliest criterion timestamp wins), and an un-mergeable inventory (.dat) clash is
decided in favour of the file with more play time — an exact play-time tie is broken by the
number of completed advancement criteria — so the least progress is lost (--overwrite
forces the source side). Nothing is ever discarded without a backup, and merged sources are
folded in so a re-run never double-counts. - Auto-migrate on rejoin (
migration.auto-migrate-on-rejoin, default on): when a player
with temporary offline data logs back in, their data is folded into their real online UUID at
pre-login — the only window where the files are not in use. Stats and advancements are merged
losslessly; an un-mergeable inventory (.dat) clash is resolved in favour of the file with more
play time (the displaced file is backed up first — never discarded without a backup), exactly like
a manual migration without--overwrite. If a conflict can't be resolved safely (e.g. backups
disabled), it is left untouched and logged for manual handling. - Optional auto-migration IP verification (
migration.auto-migrate-require-ip-match, default off):
when enabled, unattended rejoin migration only runs when the temporary outage record's IP matches
the authenticated online rejoin IP. If the IP is missing or different, IdentityBridge captures the
target UUID and leaves the record pending for manual/idb migratereview. - Startup cache backfill (async): on enable, IdentityBridge scans the UUID-keyed data files
already on disk (migration.data-locations) and resolves any real online (Java) UUID it does not
yet know to its current name via the Mojang session server, so players whose progress predates
the plugin's install are still recognised if the server later goes offline. Runs entirely off the
main thread (never blocks startup), is read-only, filters out offline-style and Bedrock UUIDs
before contacting Mojang, throttles requests, backs off on rate limits, and records definitively
unresolvable UUIDs in the identity store'signored:list so they are looked up once and skipped
thereafter. Custom templates whose{uuid}appears in the filename are discoverable too, including
root-level entries like{uuid}.dat; per-player directory templates still work for explicit
migrations but cannot be discovered by the startup directory scan. - Auth/service monitoring: periodic, detailed health checks of Mojang/Microsoft endpoints
with an overall verdict, surfaced via/idb checkand/idb status. Endpoints can declare
their ownhealthy-statuses(defaults to any 2xx). - Advisory notifications: admins are advised (console + in-game) when auth looks down while
online, or healthy while offline;monitoring.advise-on-degradedopts into acting on partial
outages too. Advisory only — never edits config, switches mode, or restarts. - Identity cache management:
/idb lookup, and a consistent action-first cache surface —
/idb cache list [<java|offline|bedrock>],/idb cache add java, and
/idb cache remove <java|offline|bedrock>./idb statusalso shows the size of the startup
backfill'signored:skip-list (when non-empty), so it is visible without opening identities.yml. - Colour codes in kick messages: the configurable
unknown-kick-messageand
ip-mismatch-kick-messagehonour legacy&-style colour/formatting codes (e.g.&c) and
&#rrggbbhex colours; plain text passes through unchanged. - Optional Bedrock/Floodgate support: detects Bedrock players, records their identity keyed
by XUID (with Floodgate UUID, linked Java UUID, and link state), and never rewrites Bedrock
UUIDs. No hard dependency; fully functional on Java-only servers. - Full account-linking support (global and local): Floodgate's global (GeyserMC hosted) and
local (database) linking are both supported transparently. Linked Bedrock players join under
their linked Java UUID (already stable, never rewritten); links are read live for online players
and resolved through Floodgate's link manager for offline ones./idb lookupaccepts a name,
UUID, or XUID and cross-references the linked Java account;/idb statusreports whether linking
is global or local. A linked Java account is also recorded as a known player
(bedrock.record-linked-java-account) so it gets Java-side continuity during an outage. - Consolidated storage: all identities live in one
identities.ymlwith uniformjava:/
offline:/bedrock:sections, written atomically (temp file + atomic move) so a crash
mid-write can never corrupt the cache. - Self-upgrading configuration: on future versions, new config keys merge in automatically
with a backup of the previous file. - Privacy & IP-match hardening controls:
privacy.store-player-ipcan disable IP persistence
entirely, andlogin-continuity.require-ip-match-strictmakes the IP-match rule refuse logins it
cannot verify (the default keeps the documented fail-open behaviour for backfilled/dynamic-IP
players).
Safety & correctness
- A manual
/idb checkrun whilemonitoring.enabledis off shows the advisory that probe implied
in the command output but never stores it — with no background monitor running, nothing could ever
refresh or clear a stored advisory, so it would otherwise be repeated to every joining admin
indefinitely./idb checkalso reports the advisory computed by its own probe rather than
re-reading shared state a concurrent scheduled check could have changed. - A scheduled auth check that was already running when
/idb reloadstopped/restarted monitoring
can no longer publish a stale last-report or advisory state after reload; scheduled probes are
generation-gated, and advisory persistence is still checked against the latest config snapshot
when the probe finishes. - The offline-mode unknown-player path refuses to record anything if it is ever handed a
non-offline-style UUID, instead of recording an unauthenticated connection as an authenticated
known player (unreachable today thanks to the pre-login offline-UUID gate; defence in depth). - With login continuity disabled, a recognised player admitted under a temporary offline UUID is
logged as a known player whose identity was not restored, instead of being mislabelled
"Unknown player" — which would contradict/idb lookupfor the same account mid-outage. - An authenticated online-mode login is only recorded as a known Java player - and only used as an
auto-migration target - when it carries a real online-style (v4) UUID. Previously, with Floodgate
installed butbedrock.enabled: false(so Bedrock detection was skipped), a Bedrock player's
v0 UUID could be cached as a known Java identity, and a same-named temporary offline record could
even be auto-migrated into that v0 UUID - the same wrong-destination hazard the join-time
online-UUID capture already guarded against. The pre-login path now enforces the identical
invariant. - The same v4-only and Java-username-shape invariants are enforced at the identity store's single
entry point for automatically-learned identities (backfillKnown), which also covers the linked
Java account recorded from a Bedrock join. That UUID/name pair comes from Floodgate's link data
(a reflective API, and for local linking an admin-run database) rather than an authenticated login,
so a non-v4 UUID or malformed name there - e.g. from a corrupt linking database or an unexpected
Floodgate result - is refused instead of being cached as an offline-mode restore target. Only the
explicit/idb cache add java --forceadmin override may store a non-v4 UUID. - The startup backfill's
ignored:(no Java profile) list and the known-player cache are mutually
exclusive: an authenticated join, backfill/link hit, or manual/idb cache add javafor an
ignored UUID clears the stale ignore marker, a cached known player is never marked ignored (e.g.
a stale NOT_FOUND lookup racing an authenticated join), and on load thejava:section wins over
a contradictory hand-editedignored:entry - so/idb statuscounts andidentities.ymlcan
never contradict each other. - Mojang profile responses are accepted only when their
idis an online-style (v4) Java UUID and
theirnameis shaped like a valid Java username. For UUID-to-profile startup backfill lookups,
an unexpected HTTP 400 is treated as a transient error rather than a definitive "no profile"
result, so the permanentignored:list cannot be poisoned by a bad response to a syntactically
valid UUID query. - Floodgate reflection now resolves API methods through a public declaring type (with an
accessibility fallback), so a Floodgate build whose ...