// Package iam is the Identity & Access bounded context: accounts, // sessions, email verification and password reset. It is the system of // record for `users`, `sessions`, `email_verification_codes` and // `password_reset_tokens` (see services/iam/migrations/0001_init.sql) — // no other service may read or write those tables directly. // // Mirrors the monolith's internal/handlers/auth.go + internal/db/users.go // + internal/auth/*.go one-for-one; see each rpc's comment for the // handler function it replaces. syntax = "proto3"; package enkly.iam.v1; option go_package = "enkly/gen/iam/v1;iamv1"; import "google/protobuf/timestamp.proto"; service IAMService { // SignUp replaces Handlers.Signup. Validates and normalizes the email, // hashes the password (PBKDF2, see internal/auth/password.go), creates // the account (or silently reuses an existing unverified one — same // anti-enumeration behavior as the monolith), issues a verification // code and publishes an iam.verification_code.issued event for the // notification service to deliver it. Never returns whether the email // already existed. rpc SignUp(SignUpRequest) returns (SignUpResponse); // ResendVerification replaces Handlers.ResendVerification. rpc ResendVerification(ResendVerificationRequest) returns (ResendVerificationResponse); // VerifyEmail replaces Handlers.VerifyEmail. rpc VerifyEmail(VerifyEmailRequest) returns (VerifyEmailResponse); // Login replaces Handlers.Login: verifies credentials (constant-time // against a dummy hash for unknown emails) and, on success, mints a // session and returns its raw token for the gateway to set as a // cookie. Never persists the raw token — only its SHA-256 hash. rpc Login(LoginRequest) returns (LoginResponse); // Logout replaces Handlers.Logout: deletes the session row for the // given raw session token. rpc Logout(LogoutRequest) returns (LogoutResponse); // ValidateSession replaces the session half of Handlers.RequireAuth / // db.GetSessionUser. Called by the gateway on every authenticated // request. rpc ValidateSession(ValidateSessionRequest) returns (ValidateSessionResponse); // ForgotPassword replaces Handlers.ForgotPassword. rpc ForgotPassword(ForgotPasswordRequest) returns (ForgotPasswordResponse); // CheckPasswordResetToken replaces the GET-time validity check in // Handlers.ResetPasswordPage (db.PasswordResetTokenValid). rpc CheckPasswordResetToken(CheckPasswordResetTokenRequest) returns (CheckPasswordResetTokenResponse); // ResetPassword replaces Handlers.ResetPassword. Also revokes every // session for the account (db.UpdatePassword's cascade delete). rpc ResetPassword(ResetPasswordRequest) returns (ResetPasswordResponse); // GetUser is used by other services (e.g. billing, when it only has a // user_id) to resolve an email address. Never returns PasswordHash. rpc GetUser(GetUserRequest) returns (User); } message User { int64 id = 1; string email = 2; bool email_verified = 3; google.protobuf.Timestamp created_at = 4; } message SignUpRequest { string email = 1; string password = 2; string password_confirm = 3; string client_ip = 4; // for the shared signup/resend rate limiter } message SignUpResponse { // Always true unless a hard infrastructure error occurred — the // monolith never reveals whether the address was already registered. bool check_inbox = 1; string email = 2; // mail_configured is echoed back so the gateway can show the same // "written to the server log instead" notice the monolith shows. bool mail_configured = 3; } message ResendVerificationRequest { string email = 1; string client_ip = 2; } message ResendVerificationResponse { bool mail_configured = 1; } message VerifyEmailRequest { string email = 1; string code = 2; string client_ip = 3; } message VerifyEmailResponse { bool verified = 1; } message LoginRequest { string email = 1; string password = 2; string client_ip = 3; } message LoginResponse { bool ok = 1; // Only one of these is meaningful depending on `ok` / `needs_verification`. bool needs_verification = 2; string session_token = 3; // raw token; gateway stores only this, in a cookie google.protobuf.Timestamp session_expires_at = 4; User user = 5; } message LogoutRequest { string session_token = 1; } message LogoutResponse {} message ValidateSessionRequest { string session_token = 1; } message ValidateSessionResponse { bool valid = 1; User user = 2; } message ForgotPasswordRequest { string email = 1; string client_ip = 2; } message ForgotPasswordResponse {} message CheckPasswordResetTokenRequest { string token = 1; } message CheckPasswordResetTokenResponse { bool valid = 1; } message ResetPasswordRequest { string token = 1; string password = 2; string password_confirm = 3; } message ResetPasswordResponse { bool ok = 1; } message GetUserRequest { int64 user_id = 1; }