diff --git a/SVSim.EmulatedEntrypoint/Controllers/AccountController.cs b/SVSim.EmulatedEntrypoint/Controllers/AccountController.cs
new file mode 100644
index 0000000..fd50d8a
--- /dev/null
+++ b/SVSim.EmulatedEntrypoint/Controllers/AccountController.cs
@@ -0,0 +1,33 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using SVSim.Database;
+using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.Account;
+
+namespace SVSim.EmulatedEntrypoint.Controllers;
+
+///
+/// /account/* — viewer profile mutations that aren't tied to a specific subsystem.
+///
+public class AccountController : SVSimController
+{
+ private readonly SVSimDbContext _db;
+
+ public AccountController(SVSimDbContext db)
+ {
+ _db = db;
+ }
+
+ [HttpPost("update_name")]
+ public async Task UpdateName([FromBody] AccountUpdateNameRequest request)
+ {
+ if (!TryGetViewerId(out long viewerId)) return Unauthorized();
+
+ var viewer = await _db.Viewers.FirstAsync(v => v.Id == viewerId);
+ viewer.DisplayName = request.Name;
+ await _db.SaveChangesAsync();
+
+ // Prod returns `data: []` — empty array, not empty object. Use an empty array literal
+ // so the translation middleware emits the right msgpack shape.
+ return Ok(Array.Empty