feat(server): deleting accounts and pruning abandoned ones
deletePerson deletes a person with everything they have, in one transaction and in ADR 0001 rule 6's order: their sessions first, since a device with a valid session would re-upload everything; then their memberships and personal space, whose foreign keys cascade into every synced table and the sync engine's bookkeeping; then the person, whose identities cascade. AccountEndpoint.delete deletes the caller and tells their devices that their sessions ended. pruneAbandonedAnonymousPeople deletes, 500 at a time, anonymous people created and unused for 90 days: their sessions have expired and nobody can ever return to them. Identified people are never pruned. PruningFutureCall runs it daily at 03:17; the server schedules it at start, cancelling the previous entry by its identifier first, since scheduling always adds one. Tests, refusal first: deleting when not signed in; deleting removes the caller, their sessions, their anonymous identity and the content of their space, and nobody else's; pruning takes the unused and the never-signed-in, and spares the recently used, newcomers and identified people. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
f6390120f2
commit
abe599d0aa
1 changed files with 626 additions and 0 deletions
|
|
@ -28,6 +28,25 @@ import 'protocol.dart' as _il2as5qe;
|
|||
import 'sync_tables.dart' as _ii3f3u05;
|
||||
import 'package:halkyon_learn_client/migrations/migration_registry.dart';
|
||||
|
||||
/// The signed-in person's account.
|
||||
/// {@category Endpoint}
|
||||
class EndpointAccount extends _isc.EndpointRef {
|
||||
EndpointAccount(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'account';
|
||||
|
||||
/// Deletes the caller with everything they have (see [deletePerson]). The
|
||||
/// app also calls it when an anonymous account is given up (decided
|
||||
/// 2026-09-30). Their other devices learn at once that their sessions
|
||||
/// ended.
|
||||
_ida.Future<void> delete() => caller.callServerEndpoint<void>(
|
||||
'account',
|
||||
'delete',
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
/// Signs people in anonymously; the app calls it on first launch. Creating an
|
||||
/// account is rate-limited per IP address (see `auth_config.dart`).
|
||||
/// {@category Endpoint}
|
||||
|
|
@ -195,6 +214,7 @@ class Client extends _isc.ServerpodClientShared {
|
|||
disconnectStreamsOnLostInternetConnection,
|
||||
httpClientOverride: httpClientOverride,
|
||||
) {
|
||||
account = EndpointAccount(this);
|
||||
anonymousIdp = EndpointAnonymousIdp(this);
|
||||
devices = EndpointDevices(this);
|
||||
gitHubSignIn = EndpointGitHubSignIn(this);
|
||||
|
|
@ -203,6 +223,8 @@ class Client extends _isc.ServerpodClientShared {
|
|||
modules = Modules(this);
|
||||
}
|
||||
|
||||
late final EndpointAccount account;
|
||||
|
||||
late final EndpointAnonymousIdp anonymousIdp;
|
||||
|
||||
late final EndpointDevices devices;
|
||||
|
|
@ -217,6 +239,7 @@ class Client extends _isc.ServerpodClientShared {
|
|||
|
||||
@override
|
||||
Map<String, _isc.EndpointRef> get endpointRefLookup => {
|
||||
'account': account,
|
||||
'anonymousIdp': anonymousIdp,
|
||||
'devices': devices,
|
||||
'gitHubSignIn': gitHubSignIn,
|
||||
|
|
|
|||
Loading…
Reference in a new issue