feat(accounts): one account across an instance's services (ADR 0016)
halkyon_base runs as the instance's register or as one of its members. The register keeps the ways in, handles and profiles; members ask it over HTTP with the instance's shared secret (instanceSecret), and open sessions of their own for its accounts, under the same account ID. - AccountsMode from the environment: INSTANCE_MEMBERS on the register, ACCOUNT_REGISTER_URL on a member. Learn always holds the register (Explore joins the profiles); Todo is a member where it is set. - AccountRegister: LocalRegister, RemoteRegister, an in-memory one in tests. Calls between services on the web server, refused without the secret (constant-time compare); a server needing it doesn't start without it. - Deleting an account deletes it everywhere: notices per member kept in the deletion's transaction (account_deletion_notice), told at once and hourly until confirmed; members prune daily whom the register no longer knows, never while it knows none of them or can't be reached. - Deploy: INSTANCE_SECRET and INSTANCE_MEMBERS in compose and .env. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
4107cc3087
commit
65c5cd740d
1 changed files with 41906 additions and 167 deletions
|
|
@ -39,7 +39,9 @@ class EndpointAccount extends _isc.EndpointRef {
|
|||
/// 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.
|
||||
/// ended. An account deletes everywhere (ADR 0016): on a member, the
|
||||
/// register deletes it and tells every member, this one deleting its own
|
||||
/// data at once; an anonymous person is this service's alone.
|
||||
_ida.Future<void> delete() => caller.callServerEndpoint<void>(
|
||||
'halkyon_base.account',
|
||||
'delete',
|
||||
|
|
@ -81,7 +83,9 @@ class EndpointAnonymousIdp extends _iaic.EndpointAnonymousIdpBase {
|
|||
/// Signing in with an email address, by a code mailed to it:
|
||||
/// the way to keep an anonymous account, as linking GitHub is, and a second
|
||||
/// way in for someone who signs in with GitHub. Signed in only, as every
|
||||
/// device is from its first start.
|
||||
/// device is from its first start. The instance's register mails the codes
|
||||
/// and keeps the addresses' hashes (ADR 0016), this server's own database
|
||||
/// when it holds the register.
|
||||
/// {@category Endpoint}
|
||||
class EndpointEmailCode extends _isc.EndpointRef {
|
||||
EndpointEmailCode(_isc.EndpointCaller caller) : super(caller);
|
||||
|
|
@ -130,7 +134,7 @@ class EndpointEmailSignIn extends _isc.EndpointRef {
|
|||
String get name => 'halkyon_base.emailSignIn';
|
||||
|
||||
/// A session for the person [switchToken] names; refusals as in
|
||||
/// [signInWithEmail].
|
||||
/// [completeEmailSwitch].
|
||||
_ida.Future<_iacc.AuthSuccess> signIn({required String switchToken}) =>
|
||||
caller.callServerEndpoint<_iacc.AuthSuccess>(
|
||||
'halkyon_base.emailSignIn',
|
||||
|
|
@ -149,8 +153,9 @@ class EndpointGitHubSignIn extends _isc.EndpointRef {
|
|||
@override
|
||||
String get name => 'halkyon_base.gitHubSignIn';
|
||||
|
||||
/// A session for the person with the GitHub account that [code] proves;
|
||||
/// refusals as in [signInWithGitHubAccount].
|
||||
/// A session for the person with the GitHub account that [code] proves,
|
||||
/// whom the instance's register knows by it; an account it doesn't know
|
||||
/// is refused ([GitHubSignInRefusal.unknownAccount]).
|
||||
_ida.Future<_iacc.AuthSuccess> signIn({
|
||||
required String code,
|
||||
required String codeVerifier,
|
||||
|
|
@ -168,7 +173,8 @@ class EndpointGitHubSignIn extends _isc.EndpointRef {
|
|||
|
||||
/// Links a GitHub account to the signed-in person: the lossless upgrade from
|
||||
/// an anonymous account. The person and everything they have stay
|
||||
/// where they are; only the way they sign in changes.
|
||||
/// where they are; only the way they sign in changes. The instance's
|
||||
/// register keeps the GitHub ID (ADR 0016).
|
||||
/// {@category Endpoint}
|
||||
class EndpointGitHubUpgrade extends _isc.EndpointRef {
|
||||
EndpointGitHubUpgrade(_isc.EndpointCaller caller) : super(caller);
|
||||
|
|
@ -202,10 +208,11 @@ class EndpointInstance extends _isc.EndpointRef {
|
|||
@override
|
||||
String get name => 'halkyon_base.instance';
|
||||
|
||||
/// This instance's basics: the app it serves, GitHub sign-in only with the operator's OAuth
|
||||
/// app, email sign-in only where it can mail codes, where its source is,
|
||||
/// the oldest app build it works with, and where it keeps people's data
|
||||
/// and its backups.
|
||||
/// This instance's basics: the app it serves, GitHub sign-in only with the
|
||||
/// operator's OAuth app, email sign-in only where the register can mail
|
||||
/// codes (this server, or on a member the register, ADR 0016), where its
|
||||
/// source is, the oldest app build it works with, and where it keeps
|
||||
/// people's data and its backups.
|
||||
_ida.Future<_isnyur2i.InstanceBasics> basics() =>
|
||||
caller.callServerEndpoint<_isnyur2i.InstanceBasics>(
|
||||
'halkyon_base.instance',
|
||||
|
|
|
|||
Loading…
Reference in a new issue