Version

Current build and changelog for every surface of Nekomara.

Changed

  • Security Mode card and its change modal reworked around the full mode-transition matrix: a new password is required on upgrade, current-password re-auth on downgrade, TOTP enrollment for Ultimate.
  • Mobile account menu rebuilt as a full-page overlay with the same item list as the desktop sidebar (Overview, Security, Support, Status, Log Out, Return Home).
  • Avatar fallback simplified to two tiers: real Minecraft skin texture, falling back directly to the default Steve skin; the account username heading now matches the Discord card's style.
  • Recent Activity's new-item entrance animation fixed so the whole list no longer replays on every new event.
  • Sticky header and step-form layering fixed on /link and /login (stacking-context isolation, z-index correction, step-slot reflow, step exit animation).

Removed

  • A Supabase anon read of the forbidden link_status view; the outage fallback now only reads the public status_snapshot row.
  • Dead account-overview.tsx component (superseded by the live /account page).

Fixed

  • A page-transition animation was breaking position: sticky/fixed overlays across the site; the confirmation modal and the account logout spinner are now portaled to document.body to avoid the issue entirely.
  • Onboarding progress bar connector-line and step expand/collapse animations.

Changed

  • Home page hero contrast and copy pass; unified the "Background images made by kael" photo credit wording across the home, login, and link pages.
  • Added a generic modal shell and used it to redesign the Security Mode change flow, plus a new "Forgot your password?" recovery flow (Discord-session identity plus a TOTP code when 2FA is enabled).

Changed

  • Security page: standardized post-save cooldown, replaced the raw TOTP input with 6-digit OTP boxes, added a secret show/copy toggle.
  • Home page tagline/description contrast pass.

Added

  • Unlink confirmation modal now shows a 30-day retention notice.

Added

  • Shared PublicHeader on the login and link pages, with an "Already Linked" state.
  • Full-bleed lobby screenshot backgrounds with forest-tinted vignettes on the home, login, and link pages; a redesigned, minimal 404 page.
  • /redirect landing page shown to unlinked accounts; a "Danger Zone" account-unlink section on the account page.

Changed

  • Player avatars now use the real Minecraft skin texture ID when one is available, replacing the username-initial placeholder.

Changed

  • Home page redesigned: removed simulated loading, added the animated hero emblem and an "Already Linked" button state.
  • Link wizard rebuilt: 6-digit code entry via individual OTP boxes, a sticky progress bar, dynamic password/2FA steps, and an inline password-strength meter.
  • Login page rebuilt to match the link wizard's step-based layout.
  • Security page restructured into a 4-column layout with a live-polling Recent Activity feed and side-by-side Sessions / Trusted IPs cards.
  • "SMP" removed from all user-facing text; switched from a shared to a per-repo .env file.

Added

  • Account "Danger Zone" (unlink) section.

Removed

  • Account Preferences section from the account page.
  • /status and /support pages (both hibernated behind an "unavailable" notice; /support later returned in a hardened, ticket-only form).

Changed

  • Replaced all simulated/mock data and localStorage-based auth with real Discord OAuth, HMAC-signed session cookies, and live Node API calls across the login, link, account, security, status, and support pages.

Added

  • Edge middleware enforcing route protection on /account and /login.
  • Security response headers (X-Frame-Options, Referrer-Policy, X-Content-Type-Options, etc.) and a client-generated Idempotency-Key header on every mutating request.

Added

  • Initial Next.js site scaffold: design system, UI primitives, verification components, account center, and security management screens, plus a /design-system reference playground (simulation-only data at this stage).

Added

  • GET /v1/meta now reports release_channel alongside contract_version.
  • Full mode-transition matrix enforced on PATCH /v1/accounts/{u}/security-mode: a new password is required on any passwordless-to-password upgrade, Strict-to-Ultimate needs TOTP enrollment only, Ultimate-to-Strict is instant and deletes the stored TOTP secret, and any password-to- passwordless downgrade requires current-password re-auth.
  • Silent per-account mode-change cooldown (5 per hour) — only surfaces once the limit is hit.
  • joined / left security events (suppressed for Strict/Ultimate accounts, where login_success/login_failed already cover the join).
  • Optional player UUID capture on POST /v1/access-check, carried into the retention record so the hourly purge sweep can enqueue a purge_playerdata action keyed on it.
  • Per-join identity self-heal against Supabase: evicts a locally-cached account if it was removed upstream, refreshes on drift, and trusts the local record during a Supabase outage.

Changed

  • A new join now supersedes any prior live session for the same account instead of creating a duplicate (fixes the reported Active Sessions duplication).
  • Enhanced-mode redeem now auto-trusts the Minecraft IP captured at link-code issuance time, never the browser/Discord IP used to redeem the code.

Changed

  • Link codes now follow an issued → claimed → completed lifecycle. The first authenticated link-progress write claims a code and removes its expiry; a claimed code no longer returns EXPIRED_CODE. Any preview/redeem/2FA-confirm/link-progress call on a code claimed by a different Discord account now returns ACCOUNT_MISMATCH.
  • Relink cooldown reduced from 600s to 60s.
  • security.mode_changed event now only fires once a mode actually applies (not while Ultimate enrollment is still pending TOTP confirmation).

Added

  • New access-check decision deny_username_retained for a username still inside its 30-day retention window — evaluated before the "no account" gate, no link code issued.
  • POST /v1/accounts/{u}/password-forgot-reset — resets a password without the current one, proven by the authenticated Discord session plus a TOTP code when 2FA is enabled. Revokes all sessions and emits a security.password_reset outbox event (later updated to include minecraft_username in that payload).

Changed

  • DELETE /v1/accounts/{u} (unlink) is now a soft-delete with a 30-day username retention period; a retained username is rejected on re-link with USERNAME_UNDER_RETENTION.

Added

  • GET /v1/accounts/{u}/retention — check retention status for a username.
  • PATCH /v1/accounts/{u}/skin-texture — update a stored skin texture hash.
  • Hourly retention purge job; Supabase mirrors for deleted accounts and skin texture.

Added

  • POST / GET / DELETE /v1/link-progress — persists partial link-wizard state to Supabase so progress survives a lost cookie.
  • sign_out security event, emitted when a session ends via quit or kick.

Removed

  • The link_status Supabase view has been dropped; the website's outage fallback now reads only the public status_snapshot row.

Changed

  • Link codes changed from a prefixed alphanumeric format (NKM-XXXXXX) to a plain 6-digit numeric string.
  • TOTP enrollment issuer/label changed from "Nekomara SMP" to "Nekomara"; "SMP" removed from all user-facing strings project-wide.

Added

  • New access-check decision deny_login_locked for an account-level login lockout.
  • skin_texture_id stored on the account record, returned in the account projection and the account.linked outbox payload.
  • Trusted-IP removal now cascades to revoke any sessions authenticated from that IP.
  • GET /v1/status/ws — WebSocket endpoint for live status push.
  • Current password is no longer required to change security mode (superseded by the full mode-transition matrix in 0.5.1, above).

Added

  • Initial implementation of all eight contract surfaces: link-code issuance/redemption, the 4-mode security engine (Standard / Enhanced / Strict / Ultimate), in-game session authentication, account and security projections, status telemetry via heartbeat, support ticket intake, the Minecraft action queue, and the Discord outbox — a zero-runtime-dependency HTTP service on node:http / node:crypto.

Added

  • Bukkit-only limbo world restrictions (block breaking/placing, item pickup, damage) without requiring ProtocolLib.
  • Handling for the purge_playerdata action: deletes a departed player's on-disk playerdata, stats, and advancements across all worlds.
  • link.status (issued vs claimed) is now parsed from access-check responses; a claimed, in-progress link routes to a distinct "verification already in progress" kick instead of the generic unlinked message.

Changed

  • All kick messages now render through MiniMessage formatting (previously some kicks used plain text).
  • Config loading now backfills any default keys missing from a player's saved config.yml / verification-security.yml on load or /nkreload, instead of silently running without them.
  • Plugin build version bumped to 0.2.0-dev (jar name, plugin.yml), targeting Paper API 1.21.11 and referencing contract v0.5.1.

Changed

  • Limbo isolation reworked to mutual invisibility between pending and regular players (lobby-style topology) instead of a full movement/interaction freeze; removed the old world-safety handlers in favor of the chat/command gate plus the new restriction listener (added two days later, above).
  • Skin texture lookup now reads the live local GameProfile only (no remote Mojang API call), removing a network dependency from the join path.
  • The public online-player count reported in the heartbeat now excludes players still in limbo.

Added

  • deny_username_retained access-check decision now recognized: kicks immediately with the retry-time message, issues no link code, and never enters limbo.

Added

  • MiniMessage-formatted kick messages; a deny_login_locked kick showing the remaining lockout time in minutes.
  • Mojang skin texture fetch, passed to access-check so the website/Discord bot can render a player's real skin (superseded by the local-profile-read approach on 2026-07-03, above).
  • /nkreload admin command for a fail-closed runtime config reload.
  • Per-player cooldown guard on /login and /2fa to prevent command-spam abuse.
  • Limbo invisibility while a player is mid-authentication, with the vanilla join broadcast suppressed until they finish (re-broadcast on success).

Changed

  • "SMP" removed from all user-facing plugin strings.
  • Build artifact renamed to Nekomara-<version>.jar; plugin.yml name changed to Nekomara.

Changed

  • kick-unlinked rewritten for Bedrock-client-friendly display; the link URL now has its query string stripped before being shown to the player.

Added

  • Initial Paper/Purpur verification gate: POST /v1/access-check on every join, routed to allow, kick, or limbo (password / password+2FA) outcomes; a 15-second status heartbeat; a 5-second action-queue poller; and a 1-second limbo-timeout sweep. Fails closed unconditionally on any transport failure or unrecognized decision.