feat(app): a wait screen for accounts that wait for the operator (ADR 0021, step 1)

An account signed in or up to on an instance whose operator approves
new accounts, or one suspended, gets no session but a wait: the device
keeps its pass, words and handle in the keyring per instance
(SecureAccountWaitStore, InstanceStorage.waitOf), the auth status is
Waiting, and SessionGate shows WaitScreen in its own app, so the start
screen's sheets go with it. Every sign-in flow hands over to it: the
password's sign-in, sign-up, reset and account reset, SimpleLogin's
sign-in, sign-up and mending; their cubits show no problem then.

The wait screen shows the handle, the four words the operator reads out
for the person to match, and that Halkyon never asks anyone to read them
out (D33); it asks where the wait stands as it opens, every 30 seconds,
as the app comes back and when asked. A new account can be deleted with
its pass, a suspended one can't (ADR 0017). Approved, it leads to the
usual sign-in, once more as before (D31); a pass the instance knows no
more ends the wait. The start screen says where new accounts wait for
approval, and offers no Create an account where the operator takes none;
both refusals (closed, too many waiting) have their words, en and de.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-25 15:29:22 +01:00
commit 7ac715cd97
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -181,6 +181,16 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
return '$instance offers no way to create an account.';
}
@override
String startSignUpsApproved(String instance) {
return 'New accounts on $instance wait until its operator approves them.';
}
@override
String startSignUpsClosed(String instance) {
return '$instance takes no new accounts: sign in with yours.';
}
@override
String get syncTitle => 'Sync';
@ -249,6 +259,58 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
@override
String get startCreateAccount => 'Create an account';
@override
String waitWaiting(String instance) {
return 'Your account waits until the operator of $instance approves it.';
}
@override
String waitSuspended(String instance) {
return 'The operator of $instance has suspended your account. Only they can lift it.';
}
@override
String waitApproved(String instance) {
return 'The operator of $instance has approved your account. Sign in once more, as you did before.';
}
@override
String waitEnded(String instance) {
return 'This sign-up has ended: the operator of $instance refused it, or it waited too long.';
}
@override
String get waitBack => 'Back to the start';
@override
String get waitMatchingCode => 'Matching code';
@override
String waitMatchingNote(String instance) {
return 'When the operator of $instance reads you four words, check that they are these. Never read them out yourself: Halkyon never asks anyone to.';
}
@override
String get waitCheckNow => 'Check now';
@override
String waitUnreachable(String instance) {
return '$instance couldn\'t be reached. It\'s asked again every 30 seconds.';
}
@override
String get waitDelete => 'Delete this account';
@override
String get waitDeleteTitle => 'Delete this account?';
@override
String get waitDeleteMessage =>
'It goes with everything it has, and nobody can sign in to it again.';
@override
String get waitDeleteFailed => 'Couldn\'t delete the account. Try again.';
@override
String get passwordAddress => 'Email address';
@ -736,6 +798,13 @@ class HalkyonAppLocalizationsEn extends HalkyonAppLocalizations {
String get passwordKeysMissing =>
'Your account\'s keys aren\'t on this device. Sign out and in again with your password here.';
@override
String get signUpsClosed => 'This instance takes no new accounts.';
@override
String get signUpsTooManyWaiting =>
'As many new accounts wait for approval as may. Try again later.';
@override
String get passwordUnsafeCosts =>
'The instance asked for your password to be checked in a way no account uses, so nothing was sent. If it happens again, the instance isn\'t the one it claims to be.';