From da0d993186e472efc7419bf4766d2409f341ffa4 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:40:37 -0700 Subject: [PATCH] docs: describe the repair path's per-account gate The XML doc on AccountSecurity.RepairMigratedPasswords still described the superseded single-switch design: it presented the flag as the only control and never mentioned Account.RepairPasswordTag, so an operator reading only that comment would enable the flag, watch nothing get repaired, and conclude the feature was broken. Its cost rationale was overstated too -- the second verify now runs only for tagged accounts, not on every failed login, so the flag alone does not widen the credential-stuffing surface. Rewrite it to say what the code does: master switch, tag independently required, set from the admin gump and cleared on a successful repair, and only ever on an account whose owner has reported the lockout -- because the repair cannot tell a mis-migrated hash from a password that merely begins with the username. Cross-reference the two by cref in both directions so either comment leads to the other. Comment-only; no behaviour change. Co-Authored-By: Claude Opus 5 (1M context) --- Projects/UOContent/Accounting/Account.cs | 3 ++- .../Accounting/Security/AccountSecurity.cs | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Projects/UOContent/Accounting/Account.cs b/Projects/UOContent/Accounting/Account.cs index 9c63a95a5..206099768 100644 --- a/Projects/UOContent/Accounting/Account.cs +++ b/Projects/UOContent/Accounting/Account.cs @@ -392,7 +392,8 @@ public partial class Account : IAccount, IComparable /// reported being locked out, and never on one that can still log in: the repair cannot tell a /// mis-migrated hash from a password that merely begins with the username, so marking a working /// account risks rewriting its credential down to whatever was submitted. Cleared automatically - /// once a repair succeeds. + /// once a repair succeeds. Necessary but not sufficient: the shard-wide + /// switch must be on as well. /// public const string RepairPasswordTag = "RepairMigratedPassword"; diff --git a/Projects/UOContent/Accounting/Security/AccountSecurity.cs b/Projects/UOContent/Accounting/Security/AccountSecurity.cs index c2c495c2f..a156f4a61 100644 --- a/Projects/UOContent/Accounting/Security/AccountSecurity.cs +++ b/Projects/UOContent/Accounting/Security/AccountSecurity.cs @@ -36,11 +36,17 @@ public static class AccountSecurity public static PasswordProtectionAlgorithm CurrentAlgorithm { get; set; } /// - /// Enables a one-time repair for accounts whose password was corrupted by the pre-fix - /// SetPassword, which hashed username + password but tagged it with an algorithm whose phrase - /// rule omits the username. Off by default: the repair costs a second verify on every FAILED - /// login, and failed logins are the credential-stuffing surface. Turn it on for a migration - /// window, then off again. + /// Shard-wide master switch for the one-time repair of accounts whose password was corrupted by + /// the pre-fix SetPassword, which stored the credential under the wrong family's phrase rule. + /// This flag alone repairs nothing: an account is only repaired when it *also* carries the + /// tag, which an operator adds from the admin gump + /// (Account Details -> Tags -> Add Tag) and which is cleared automatically once the repair + /// succeeds. Tag only an account whose owner has actually reported being locked out, never one + /// that can still log in: the repair cannot distinguish a mis-migrated hash from a password that + /// merely begins with the username, so tagging a working account risks rewriting its credential + /// down to whatever was submitted. Off by default because the repair costs a second verify on a + /// failed login -- for tagged accounts only, so the credential-stuffing surface is unaffected by + /// the flag on its own. Turn it on for a migration window, then off again. /// public static bool RepairMigratedPasswords { get; set; }