fix(auth): a reset waits while its owner is held out, and devices show it
The full reading's H1: an owner could be kept from calling a reset off, and the reset then went through. Whoever knew the password and had the mailbox asked an authenticators' reset and kept the codes waiting, so the owner's sign-ins were refused until it took effect; whoever had the mailbox filled the address's proofs ceiling from three networks and completed an account reset. Now every hold-out of the owner after a reset was asked (a wait that begins, an attempt a wait refuses, a sign-in or proof refused by the address's ceiling) moves the account's resets not carried out to take effect no sooner than 72 hours after it ends (pushOutResets). A reset carried out (the password alone signing in until an authenticator is confirmed) is never pushed, nor a lapsed one brought back. Signed-in devices are told too: SignInWays carries when a waiting reset of each kind takes effect, the account section shows them with Call it off, which takes the owner's proof (password and code; password. callOffResets, forwarded by members) and calls every reset off, as no wait holds a signed-in owner's proof back. Texts in English and German. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
4d1cd2045c
commit
9d0d037c86
2 changed files with 1022 additions and 18 deletions
|
|
@ -23,6 +23,8 @@ abstract class SignInWays
|
|||
bool? passwordOnly,
|
||||
bool? secondFactorWorks,
|
||||
this.sessionEndedForProofsAt,
|
||||
this.authenticatorResetAt,
|
||||
this.accountResetAt,
|
||||
}) : password = password ?? false,
|
||||
authenticator = authenticator ?? false,
|
||||
passwordOnly = passwordOnly ?? false,
|
||||
|
|
@ -36,6 +38,8 @@ abstract class SignInWays
|
|||
bool? passwordOnly,
|
||||
bool? secondFactorWorks,
|
||||
DateTime? sessionEndedForProofsAt,
|
||||
DateTime? authenticatorResetAt,
|
||||
DateTime? accountResetAt,
|
||||
}) = _SignInWaysImpl;
|
||||
|
||||
factory SignInWays.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
|
|
@ -62,6 +66,16 @@ abstract class SignInWays
|
|||
: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['sessionEndedForProofsAt'],
|
||||
),
|
||||
authenticatorResetAt: jsonSerialization['authenticatorResetAt'] == null
|
||||
? null
|
||||
: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['authenticatorResetAt'],
|
||||
),
|
||||
accountResetAt: jsonSerialization['accountResetAt'] == null
|
||||
? null
|
||||
: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['accountResetAt'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +104,14 @@ abstract class SignInWays
|
|||
/// password (ADR 0017, the fourth reading); null for none.
|
||||
DateTime? sessionEndedForProofsAt;
|
||||
|
||||
/// When a reset of the authenticators waiting (or due, not carried out)
|
||||
/// takes effect, so a signed-in device shows it and its owner calls it
|
||||
/// off with their proof (ADR 0017, the full reading's H1); null for none.
|
||||
DateTime? authenticatorResetAt;
|
||||
|
||||
/// When a reset of the account waiting (or due) takes effect, alike.
|
||||
DateTime? accountResetAt;
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
|
|
@ -101,6 +123,8 @@ abstract class SignInWays
|
|||
bool? passwordOnly,
|
||||
bool? secondFactorWorks,
|
||||
DateTime? sessionEndedForProofsAt,
|
||||
DateTime? authenticatorResetAt,
|
||||
DateTime? accountResetAt,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
|
|
@ -114,6 +138,9 @@ abstract class SignInWays
|
|||
'secondFactorWorks': secondFactorWorks,
|
||||
if (sessionEndedForProofsAt != null)
|
||||
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||
if (authenticatorResetAt != null)
|
||||
'authenticatorResetAt': authenticatorResetAt?.toJson(),
|
||||
if (accountResetAt != null) 'accountResetAt': accountResetAt?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +156,9 @@ abstract class SignInWays
|
|||
'secondFactorWorks': secondFactorWorks,
|
||||
if (sessionEndedForProofsAt != null)
|
||||
'sessionEndedForProofsAt': sessionEndedForProofsAt?.toJson(),
|
||||
if (authenticatorResetAt != null)
|
||||
'authenticatorResetAt': authenticatorResetAt?.toJson(),
|
||||
if (accountResetAt != null) 'accountResetAt': accountResetAt?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -149,6 +179,8 @@ class _SignInWaysImpl extends SignInWays {
|
|||
bool? passwordOnly,
|
||||
bool? secondFactorWorks,
|
||||
DateTime? sessionEndedForProofsAt,
|
||||
DateTime? authenticatorResetAt,
|
||||
DateTime? accountResetAt,
|
||||
}) : super._(
|
||||
gitHub: gitHub,
|
||||
email: email,
|
||||
|
|
@ -157,6 +189,8 @@ class _SignInWaysImpl extends SignInWays {
|
|||
passwordOnly: passwordOnly,
|
||||
secondFactorWorks: secondFactorWorks,
|
||||
sessionEndedForProofsAt: sessionEndedForProofsAt,
|
||||
authenticatorResetAt: authenticatorResetAt,
|
||||
accountResetAt: accountResetAt,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [SignInWays]
|
||||
|
|
@ -171,6 +205,8 @@ class _SignInWaysImpl extends SignInWays {
|
|||
bool? passwordOnly,
|
||||
bool? secondFactorWorks,
|
||||
Object? sessionEndedForProofsAt = _Undefined,
|
||||
Object? authenticatorResetAt = _Undefined,
|
||||
Object? accountResetAt = _Undefined,
|
||||
}) {
|
||||
return SignInWays(
|
||||
gitHub: gitHub ?? this.gitHub,
|
||||
|
|
@ -182,6 +218,12 @@ class _SignInWaysImpl extends SignInWays {
|
|||
sessionEndedForProofsAt: sessionEndedForProofsAt is DateTime?
|
||||
? sessionEndedForProofsAt
|
||||
: this.sessionEndedForProofsAt,
|
||||
authenticatorResetAt: authenticatorResetAt is DateTime?
|
||||
? authenticatorResetAt
|
||||
: this.authenticatorResetAt,
|
||||
accountResetAt: accountResetAt is DateTime?
|
||||
? accountResetAt
|
||||
: this.accountResetAt,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -489,6 +489,18 @@ class EndpointPassword extends _isc.EndpointRef {
|
|||
},
|
||||
);
|
||||
|
||||
/// Calls off every reset of the caller's account waiting, with the
|
||||
/// owner's [proof] (ADR 0017, the full reading's H1: a signed-in device
|
||||
/// shows the resets, `SignInWays`), even while the account's codes wait;
|
||||
/// counted against this session as every owner's proof is. Refusals as
|
||||
/// `callOffResets`' ([PasswordRefusedException]).
|
||||
_ida.Future<void> callOffResets({required _ikq9b2yz.OwnerProof proof}) =>
|
||||
caller.callServerEndpoint<void>(
|
||||
'halkyon_base.password',
|
||||
'callOffResets',
|
||||
{'proof': proof},
|
||||
);
|
||||
|
||||
/// A new recovery phrase: [recoveryKeys], the caller's keys wrapped under
|
||||
/// it on the device, replace the old wrapping, and [recoveryProofKey], the
|
||||
/// public half of its proof key, the old one, with the owner's [proof], as
|
||||
|
|
|
|||
Loading…
Reference in a new issue