Some checks are pending
Build / build (push) Waiting to run
Player YOU500 lost full inventory at 17:13:39 due to AuthLimbo teleportAsync rejection during AuthMe-driven post-login teleport. Items void-dropped, no backup recoverable. AUDIT-2026-05-07.md traces code path (LoginListener.java:128, 172-175) and ranks fix candidates F1-F7. ROADMAP.md slots them across v1.1.0/v1.2.0/v1.3.0 with priority and acceptance criteria. P0 fixes pending source change: - F1: VOID-damage guard (EntityDamageEvent listener at HIGHEST) - F2: recovery on teleportAsync false (sync-TP back to limbo + retry) - F4: pre-empt AuthMe internal teleport (LoginEvent at LOWEST) Privacy posture preserved across all proposed changes.
127 lines
4.6 KiB
Markdown
127 lines
4.6 KiB
Markdown
# ROADMAP — AuthLimbo
|
||
|
||
Tracked work items for the plugin. Format: priority, ID, title, status,
|
||
acceptance criteria. Source-of-truth for what needs to ship next.
|
||
|
||
Status legend:
|
||
- `OPEN` — not started
|
||
- `WIP` — in progress on a branch
|
||
- `BLOCKED` — waiting on upstream / external
|
||
- `DONE` — landed on `main`, in a tagged release
|
||
|
||
---
|
||
|
||
## P0 — must-fix (data-loss bugs)
|
||
|
||
### F1 · OPEN · Void-damage guard during post-login restore
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F1. Triggered by
|
||
YOU500 incident on 2026-05-07 — full inventory loss to void on login.
|
||
|
||
Acceptance:
|
||
- New `Set<UUID> pendingTransit` in `LoginListener`.
|
||
- UUID added on `LoginEvent`, removed on TP success or final retry give-up.
|
||
- `EntityDamageEvent` listener at `EventPriority.HIGHEST`: if
|
||
`entity instanceof Player`, UUID in `pendingTransit`, cause is `VOID` →
|
||
`setCancelled(true)` and `player.teleport(limboManager.spawn())`
|
||
*synchronously* (we need to land before the next tick voids them again).
|
||
- Covered by test plan §5.1 and §5.4 in AUDIT-2026-05-07.md.
|
||
|
||
### F2 · OPEN · Recovery when teleportAsync returns false
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F2.
|
||
|
||
Today: `LoginListener.java:172–175` only logs. After fix:
|
||
- On `success == false`: synchronously TP to limbo spawn, schedule one
|
||
retry of `doTeleport` after 20 ticks.
|
||
- Track retry count per UUID (max 3). After 3 failures: drop into F6 path.
|
||
- Also wire the `exceptionally` branches (lines 180–185, 186–191) into
|
||
the same recovery.
|
||
|
||
Acceptance: test plan §5.2 passes — invalid coords trigger recovery, no
|
||
void death, admin sees logged retries.
|
||
|
||
### F4 · OPEN · Pre-empt AuthMe's own broken teleport
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F4. Implements
|
||
option (a): add a second `LoginEvent` handler at `EventPriority.LOWEST`
|
||
that immediately teleports the player back to limbo spawn. AuthMe's
|
||
internal teleport then runs against an irrelevant location, our MONITOR
|
||
handler wins last.
|
||
|
||
Depends on: F1 (so void damage during the LOWEST→MONITOR window is
|
||
guarded).
|
||
|
||
Acceptance: in test plan §5.6, log shows AuthMe's TP line followed by no
|
||
`left the confines` event before our authoritative TP fires.
|
||
|
||
---
|
||
|
||
## P1 — defensive (failure modes we know about)
|
||
|
||
### F3 · OPEN · Pre-flight 3x3 chunk preload before teleportAsync
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F3.
|
||
|
||
In `doTeleport` (LoginListener.java:133), before calling
|
||
`getChunkAtAsyncUrgently` on the centre chunk, also `addPluginChunkTicket`
|
||
on the eight neighbours. Release all nine tickets via the existing
|
||
`scheduleTicketRelease` path (extend it to take a list).
|
||
|
||
Acceptance: test plan §5.1 passes even when the centre chunk is on a
|
||
section boundary that previously triggered "loaded but not ready".
|
||
|
||
### F5 · OPEN · Inventory snapshot + auto-restore on transit death
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F5. Defence in
|
||
depth — even if F1–F4 all fail, no inventory is lost.
|
||
|
||
- On `AuthMeAsyncPreLoginEvent` (in addition to chunk pin), snapshot
|
||
player inventory + xp + location into `Map<UUID, Snapshot>`.
|
||
- Optionally persist to `plugins/AuthLimbo/snapshots/<uuid>.nbt` for
|
||
crash-survivability.
|
||
- On `PlayerDeathEvent` while UUID in `pendingTransit`:
|
||
`event.getDrops().clear()`, `event.setKeepInventory(true)`,
|
||
`event.setKeepLevel(true)`. On `PlayerRespawnEvent`, restore from
|
||
snapshot if needed and TP to limbo spawn for re-restore.
|
||
- Snapshot discarded 30 s after successful TP.
|
||
|
||
Acceptance: test plan §5.5 — induced death during transit yields full
|
||
inventory on respawn.
|
||
|
||
---
|
||
|
||
## P2 — nice-to-have
|
||
|
||
### F6 · OPEN · Spectator-mode admin-alert fallback
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F6. After 3 failed
|
||
retries (F2): set spectator, TP to overworld default spawn, console log
|
||
+ optional Discord webhook config key. Player gets a message to ping
|
||
staff for manual `/authlimbo tp`.
|
||
|
||
### F7 · OPEN · Telemetry counters + `/authlimbo stats`
|
||
|
||
Source: [AUDIT-2026-05-07.md](AUDIT-2026-05-07.md) §4 F7.
|
||
|
||
Track per-session counters: restore_success, restore_retry,
|
||
restore_fail, void_damage_blocked, snapshot_restored. Expose via a new
|
||
`/authlimbo stats` subcommand. Reset on plugin reload.
|
||
|
||
---
|
||
|
||
## Done
|
||
|
||
(Nothing landed since v1.0.0 release on 2026-04-30. First post-1.0
|
||
release will be triggered by F1+F2+F4 landing as v1.1.0.)
|
||
|
||
---
|
||
|
||
## Release plan
|
||
|
||
- **v1.1.0** — F1, F2, F4 (data-loss fix). Target: ASAP.
|
||
- **v1.2.0** — F3, F5 (defence in depth). Target: within 2 weeks.
|
||
- **v1.3.0** — F6, F7 (ops UX). Target: opportunistic.
|
||
|
||
Privacy invariant (limbo-on-join, no overworld exposure pre-auth) must
|
||
hold across every release. See `AUDIT-2026-05-07.md` §6.
|