auth-limbo/CHANGELOG.md
s8n afea34badc fix(login): F1+F2+F4 — void-death guard, retry recovery, AuthMe pre-empt
Closes the YOU500 inventory-loss path documented in AUDIT-2026-05-07.md.
Bumps to 1.1.0 per CHANGELOG.

F1 — void-damage guard: new EntityDamageEvent listener at HIGHEST,
ignoreCancelled=true. While a UUID sits in pendingTransit, DamageCause.VOID
is cancelled, the player is healed to 20.0, fall/fire reset, sync-TP back
to limbo spawn. Console gets a WARN with intended TP target. This single
guard would have saved YOU500's inventory.

F2 — recovery on teleportAsync false / exception: replaces the previous
log-only branch in doTeleport. On failure: sync-TP to limbo spawn, bump
per-UUID retry counter, schedule retry after 30 ticks. After MAX_RETRIES=3
failures: leave at limbo spawn in GameMode.SPECTATOR, log SEVERE with full
saved coords + reason, alert console for manual `/authlimbo tp` action.
Player stays in pendingTransit across retries so F1 keeps protecting them.

F4 — pre-empt AuthMe's broken teleport: new LoginEvent handler at
EventPriority.LOWEST that adds the UUID to pendingTransit and sync-TPs
the player to limbo spawn BEFORE AuthMe-ReReloaded's own internal
post-login teleport runs. AuthMe's teleport then operates against an
irrelevant location; the existing MONITOR handler still wins last with
the authoritative restore. Net effect: closes the void-death window even
when the saved chunk is far out and slow to load.

Internal: ConcurrentHashMap-backed pendingTransit set + retryCounts map,
both watchdog-timed-out after 5 s so we never leak entries on edge cases.
No new Maven dependencies.

Privacy invariant unchanged — F4 actually strengthens limbo-on-join by
guaranteeing the limbo position is reasserted at LOGIN-LOWEST.

Build: mvn -B clean package (in maven:3.9-eclipse-temurin-21 container) ->
BUILD SUCCESS, AuthLimbo-1.1.0.jar produced.
2026-05-07 17:50:00 +01:00

4.6 KiB

Changelog

All notable changes to AuthLimbo are documented here. The format is based on Keep a Changelog, and the project follows Semantic Versioning.

[1.1.0] - 2026-05-07

Data-loss bug fix release. Triggered by the YOU500 incident on racked.ru at 2026-05-07 17:13:39 UTC — full inventory void-death during AuthMe's post-login teleport. See AUDIT-2026-05-07.md for the full forensic trace and ROADMAP.md for tracking.

Added

  • F1 — VOID-damage guard during post-login restore. New EntityDamageEvent listener at EventPriority.HIGHEST, ignoreCancelled=true. While a player UUID sits in pendingTransit (post-LoginEvent, pre-restore-success), DamageCause.VOID events are cancelled, the player is healed to full, and sync-teleported back to limbo spawn. Console gets a WARN with the player name + intended TP target. This single guard would have saved YOU500's inventory.
  • F2 — Recovery on teleportAsync future == false. The previous log-and-abandon branch in LoginListener.doTeleport is replaced with a retry loop. On any failure (false future, exceptional future, or chunk-load throw): synchronously snap the player back to limbo spawn, increment a per-UUID retry counter, schedule another doTeleport after 30 ticks (~1.5 s). After 3 failures: leave the player at limbo spawn in GameMode.SPECTATOR, log SEVERE with full saved coords + retry count, and alert console with manual-intervention instructions (/authlimbo tp <player>). Players stay in pendingTransit across retries so F1 keeps protecting them.
  • F4 — Pre-empt AuthMe's broken teleport. New LoginEvent listener at EventPriority.LOWEST (runs BEFORE AuthMe-ReReloaded's own internal post-login teleport). Action: synchronously TP the player back to limbo spawn and add their UUID to pendingTransit. AuthMe's subsequent teleport then operates against an irrelevant location, and our existing MONITOR handler still wins last with the authoritative restore. Net effect: closes the void-death window even when the saved chunk is far out and slow to load.

Internal

  • New Set<UUID> pendingTransit (ConcurrentHashMap.newKeySet) and Map<UUID, Integer> retryCounts on LoginListener. Both are watchdog-timed-out after 5 s so we never leak entries on edge cases.
  • Constants: MAX_RETRIES=3, RETRY_DELAY_TICKS=30, PENDING_TIMEOUT_TICKS=100.
  • No new Maven dependencies. No new public API.

Privacy

  • Limbo-on-join invariant unchanged. F4 actually strengthens it by guaranteeing the limbo position is reasserted at LOGIN-LOWEST.

Test plan (reproduces YOU500 in dev Paper 1.21.x + AuthMe-ReReloaded fork b49)

  • Set saved coord far out (e.g. X=10000, Z=10000) in authme.db for a test account so the chunk is unloaded at login. Restart server. Login. Expect: F4 sync-TPs to limbo spawn first; F2 retries on false future; F1 catches any VOID damage during transit; player ends up at saved coords with full inventory.
  • Set saved Y above world build limit (e.g. 5000). Login. Expect: F2 recovery branch retries up to 3 times, then drops the player into spectator at limbo spawn with admin alert.
  • Trigger a synthetic VOID damage during transit (debug command). Expect: F1 cancels the damage, snaps player back to limbo spawn at full health, restore continues.

[1.0.0] - 2026-04-30

Initial public release.

Added

  • Auth-limbo void world manager. Creates and configures auth_limbo world with no Multiverse-Core dependency.
  • AuthMe LoginEvent listener at MONITOR priority. Reads saved quit coordinates directly from plugins/AuthMe/authme.db (SQLite, read-only) and forces a delayed teleportAsync to those coordinates after AuthMe's own broken teleport runs.
  • AuthMeAsyncPreLoginEvent listener for chunk preload. Pins the destination chunk via Chunk#addPluginChunkTicket before login completes to avoid the unloaded-chunk race documented in Paper #4085. Tickets are released 5 seconds after the teleport completes.
  • Optional 5x5 barrier platform at limbo spawn so unauth players can't fall into the void.
  • /authlimbo reload and /authlimbo tp <player> admin commands gated on authlimbo.admin.
  • Shaded SQLite JDBC driver (org.xerial:sqlite-jdbc 3.46.1.3, relocated to ru.authlimbo.shaded.sqlite) so the plugin reads AuthMe's database without classpath collisions.

Compatibility

  • Paper / Purpur 1.21.11 (api-version 1.21).
  • Java 21.
  • AuthMe-ReReloaded HaHaWTH fork b49 (fr.xephi:authme:5.6.0-FORK-b49) as a hard dependency.