syntax = "proto3"; package forest.v1; import "google/protobuf/timestamp.proto"; // UsersService handles user management, authentication, and profile operations. service UsersService { // Authentication rpc Register(RegisterRequest) returns (RegisterResponse); rpc Login(LoginRequest) returns (LoginResponse); rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse); rpc Logout(LogoutRequest) returns (LogoutResponse); // User CRUD rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); // Password management rpc ChangePassword(ChangePasswordRequest) returns (ChangePasswordResponse); // Email management rpc AddEmail(AddEmailRequest) returns (AddEmailResponse); rpc VerifyEmail(VerifyEmailRequest) returns (VerifyEmailResponse); rpc RemoveEmail(RemoveEmailRequest) returns (RemoveEmailResponse); // Social / OAuth login rpc OAuthLogin(OAuthLoginRequest) returns (OAuthLoginResponse); rpc LinkOAuthProvider(LinkOAuthProviderRequest) returns (LinkOAuthProviderResponse); rpc UnlinkOAuthProvider(UnlinkOAuthProviderRequest) returns (UnlinkOAuthProviderResponse); // Personal access tokens rpc CreatePersonalAccessToken(CreatePersonalAccessTokenRequest) returns (CreatePersonalAccessTokenResponse); rpc ListPersonalAccessTokens(ListPersonalAccessTokensRequest) returns (ListPersonalAccessTokensResponse); rpc DeletePersonalAccessToken(DeletePersonalAccessTokenRequest) returns (DeletePersonalAccessTokenResponse); // Token introspection (requires valid access token) rpc TokenInfo(TokenInfoRequest) returns (TokenInfoResponse); // MFA rpc SetupMfa(SetupMfaRequest) returns (SetupMfaResponse); rpc VerifyMfa(VerifyMfaRequest) returns (VerifyMfaResponse); rpc DisableMfa(DisableMfaRequest) returns (DisableMfaResponse); } // ─── Core types ────────────────────────────────────────────────────── message User { string user_id = 1; // UUID string username = 2; repeated UserEmail emails = 3; repeated OAuthConnection oauth_connections = 4; bool mfa_enabled = 5; google.protobuf.Timestamp created_at = 6; google.protobuf.Timestamp updated_at = 7; } message UserEmail { string email = 1; bool verified = 2; } enum OAuthProvider { OAUTH_PROVIDER_UNSPECIFIED = 0; OAUTH_PROVIDER_GITHUB = 1; OAUTH_PROVIDER_GOOGLE = 2; OAUTH_PROVIDER_GITLAB = 3; OAUTH_PROVIDER_MICROSOFT = 4; } message OAuthConnection { OAuthProvider provider = 1; string provider_user_id = 2; string provider_email = 3; google.protobuf.Timestamp linked_at = 4; } // ─── Authentication ────────────────────────────────────────────────── message RegisterRequest { string username = 1; string email = 2; string password = 3; } message RegisterResponse { User user = 1; AuthTokens tokens = 2; } message LoginRequest { // Login with either username or email oneof identifier { string username = 1; string email = 2; } string password = 3; } message LoginResponse { User user = 1; AuthTokens tokens = 2; } message RefreshTokenRequest { string refresh_token = 1; } message RefreshTokenResponse { AuthTokens tokens = 1; } message LogoutRequest { string refresh_token = 1; } message LogoutResponse {} message AuthTokens { string access_token = 1; string refresh_token = 2; int64 expires_in_seconds = 3; } // ─── Token introspection ───────────────────────────────────────────── message TokenInfoRequest {} message TokenInfoResponse { string user_id = 1; int64 expires_at = 2; // Unix timestamp (seconds) } // ─── User CRUD ─────────────────────────────────────────────────────── message GetUserRequest { oneof identifier { string user_id = 1; string username = 2; string email = 3; } } message GetUserResponse { User user = 1; } message UpdateUserRequest { string user_id = 1; optional string username = 2; } message UpdateUserResponse { User user = 1; } message DeleteUserRequest { string user_id = 1; } message DeleteUserResponse {} message ListUsersRequest { int32 page_size = 1; string page_token = 2; optional string search = 3; // search across username, email } message ListUsersResponse { repeated User users = 1; string next_page_token = 2; int32 total_count = 3; } // ─── Password management ───────────────────────────────────────────── message ChangePasswordRequest { string user_id = 1; string current_password = 2; string new_password = 3; } message ChangePasswordResponse {} // ─── Email management ──────────────────────────────────────────────── message AddEmailRequest { string user_id = 1; string email = 2; } message AddEmailResponse { UserEmail email = 1; } message VerifyEmailRequest { string user_id = 1; string email = 2; } message VerifyEmailResponse {} message RemoveEmailRequest { string user_id = 1; string email = 2; } message RemoveEmailResponse {} // ─── OAuth / Social login ──────────────────────────────────────────── message OAuthLoginRequest { OAuthProvider provider = 1; string authorization_code = 2; string redirect_uri = 3; } message OAuthLoginResponse { User user = 1; AuthTokens tokens = 2; bool is_new_user = 3; } message LinkOAuthProviderRequest { string user_id = 1; OAuthProvider provider = 2; string authorization_code = 3; string redirect_uri = 4; } message LinkOAuthProviderResponse { OAuthConnection connection = 1; } message UnlinkOAuthProviderRequest { string user_id = 1; OAuthProvider provider = 2; } message UnlinkOAuthProviderResponse {} // ─── Personal access tokens ────────────────────────────────────────── message PersonalAccessToken { string token_id = 1; // UUID string name = 2; repeated string scopes = 3; google.protobuf.Timestamp expires_at = 4; google.protobuf.Timestamp last_used = 5; google.protobuf.Timestamp created_at = 6; } message CreatePersonalAccessTokenRequest { string user_id = 1; string name = 2; repeated string scopes = 3; // Duration in seconds; 0 = no expiry int64 expires_in_seconds = 4; } message CreatePersonalAccessTokenResponse { PersonalAccessToken token = 1; // The raw token value, only returned on creation string raw_token = 2; } message ListPersonalAccessTokensRequest { string user_id = 1; } message ListPersonalAccessTokensResponse { repeated PersonalAccessToken tokens = 1; } message DeletePersonalAccessTokenRequest { string token_id = 1; } message DeletePersonalAccessTokenResponse {} // ─── MFA ───────────────────────────────────────────────────────────── enum MfaType { MFA_TYPE_UNSPECIFIED = 0; MFA_TYPE_TOTP = 1; } message SetupMfaRequest { string user_id = 1; MfaType mfa_type = 2; } message SetupMfaResponse { string mfa_id = 1; // UUID // TOTP provisioning URI (otpauth://...) string provisioning_uri = 2; // Base32-encoded secret for manual entry string secret = 3; } message VerifyMfaRequest { string mfa_id = 1; // The TOTP code to verify setup string code = 2; } message VerifyMfaResponse {} message DisableMfaRequest { string user_id = 1; // Current TOTP code to confirm disable string code = 2; } message DisableMfaResponse {}