//! el-auth — Built-in authentication and authorization for el-ui.
//!
//! Not a library you add. Native to the framework.
//!
//! ```toml
//! [auth]
//! provider = "jwt"
//! jwt_secret_env = "JWT_SECRET"
//! session_store = "memory"   # or "engram"
//! ```
//!
//! ## Engram-native sessions
//!
//! Use `EngramSessionStore` (in `engram_session`) for sessions backed by the
//! Engram identity graph. Sessions are graph nodes — server-side invalidation
//! works even with stateless JWTs.

pub mod context;
pub mod engram_session;
pub mod jwt;
pub mod middleware;
pub mod roles;
pub mod session;

pub use context::{AuthContext, AuthUser};
pub use engram_session::EngramSessionStore;
pub use jwt::{JwtClaims, JwtProvider};
pub use middleware::AuthMiddleware;
pub use roles::{Permission, Role, RoleRegistry};
pub use session::SessionProvider;

#[cfg(test)]
mod tests;

use thiserror::Error;

#[derive(Debug, Error)]
pub enum AuthError {
    #[error("invalid credentials")]
    InvalidCredentials,
    #[error("token expired")]
    TokenExpired,
    #[error("token invalid: {0}")]
    TokenInvalid(String),
    #[error("session not found")]
    SessionNotFound,
    #[error("forbidden: requires permission '{0}'")]
    Forbidden(String),
    #[error("auth configuration error: {0}")]
    Config(String),
}

pub type AuthResult<T> = Result<T, AuthError>;

/// The AuthProvider trait — implemented by JWT, Session, OAuth providers.
pub trait AuthProvider: Send + Sync {
    /// The provider name (e.g., "jwt", "session").
    fn name(&self) -> &'static str;

    /// Verify a token/session string and return the auth context.
    fn verify(&self, token: &str) -> AuthResult<AuthContext>;

    /// Issue a new token/session for an authenticated user.
    fn issue(&self, user: AuthUser, role_registry: &RoleRegistry) -> AuthResult<String>;

    /// Revoke a token/session (for logout).
    fn revoke(&self, token: &str) -> AuthResult<()>;
}
