namespace MoShiro.Backend.Application; public sealed record UserRecord(string Id, string Username, byte[] PasswordHash, byte[] PasswordSalt, int Iterations, long CreatedAtMs); public sealed record SessionRecord(byte[] IdSha256, string UserId, byte[] CsrfToken, long CreatedAtMs, long ExpiresAtMs, string AuthMethod = AuthMethods.Password); public sealed record ApiTokenRecord(string Id, string Name, IReadOnlyList Capabilities, byte[] TokenSha256, long CreatedAtMs, long? LastUsedAtMs, long? ExpiresAtMs, long? RevokedAtMs); public interface IAuthStore { ValueTask CountUsersAsync(CancellationToken ct); ValueTask GetUserByNameAsync(string username, CancellationToken ct); ValueTask GetUserAsync(string id, CancellationToken ct); ValueTask> ListUsersAsync(CancellationToken ct); /// 用户名已存在时返回 false。 ValueTask CreateUserAsync(UserRecord user, CancellationToken ct); ValueTask UpdatePasswordAsync(string userId, byte[] hash, byte[] salt, int iterations, CancellationToken ct); ValueTask CreateSessionAsync(SessionRecord session, CancellationToken ct); ValueTask GetSessionAsync(byte[] idSha256, CancellationToken ct); ValueTask DeleteSessionAsync(byte[] idSha256, CancellationToken ct); ValueTask DeleteExpiredSessionsAsync(long nowMs, CancellationToken ct); ValueTask CreateApiTokenAsync(ApiTokenRecord token, CancellationToken ct); /// 凭证 id 已经存在时返回 false。 ValueTask AddPasskeyAsync(PasskeyRecord passkey, CancellationToken ct); ValueTask FindPasskeyAsync(string credentialId, CancellationToken ct); ValueTask> ListPasskeysAsync(string userId, CancellationToken ct); /// 所有用户的 passkey(操作员集合从这里取)。 ValueTask> ListAllPasskeysAsync(CancellationToken ct); /// 只能删自己的。 ValueTask DeletePasskeyAsync(string userId, string credentialId, CancellationToken ct); ValueTask TouchPasskeyAsync(string credentialId, long signCount, long nowMs, CancellationToken ct); ValueTask FindApiTokenAsync(byte[] tokenSha256, CancellationToken ct); ValueTask> ListApiTokensAsync(CancellationToken ct); ValueTask RevokeApiTokenAsync(string id, long nowMs, CancellationToken ct); ValueTask TouchApiTokenAsync(string id, long nowMs, CancellationToken ct); }