diff --git a/TASKS.md b/TASKS.md index 3fc034a..f0e0cde 100644 --- a/TASKS.md +++ b/TASKS.md @@ -145,6 +145,7 @@ Progress: - Phase 0 / task `0.1`: создан `crank-core::ext` module skeleton - Phase 0 / task `0.2`: `MachineCredentialVerifier` и связанные типы вынесены из `apps/mcp-server` в public seam `crank_core::ext::auth` - Phase 0 / task `0.3`: введены `MachineTokenIssuer`, `NoMachineTokenIssuer`, `TokenIssuerActor` и `TokenIssuerError` в public seam `crank_core::ext::auth` + - Phase 0 / task `0.4`: введены `IdentityProvider`, `IdentityProviderKind`, `IdentityError`, `LoginPayload`, `LoginOutcome` и public forwarder type `AuthenticatedIdentity` в `crank_core::ext::auth` - Phase 0 / task `0.5`: введены `PolicyEngine`, `SessionActor`, `PolicyAction`, `PolicyScope`, `PolicyDecision` и default `OwnerOnlyPolicyEngine` в public seam `crank_core::ext::access` - Phase 0 / task `0.6`: введены `AuditSink`, `NoopAuditSink`, `AuditEventId` и базовые audit-типы в public seam `crank_core::ext::audit` - Phase 0 / task `0.7`: введены `CapabilityProfile` и `CommunityCapabilityProfile`, а `admin-api` capability payload теперь собирается через public seam вместо локального literal diff --git a/crates/crank-core/src/ext/auth.rs b/crates/crank-core/src/ext/auth.rs index 620f270..708a3a0 100644 --- a/crates/crank-core/src/ext/auth.rs +++ b/crates/crank-core/src/ext/auth.rs @@ -4,8 +4,8 @@ use async_trait::async_trait; use crate::{ IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest, IssuedAgentTokenResponse, - MachineAccessMode, MembershipRole, OperationSecurityLevel, PlatformApiKeyScope, UserId, - WorkspaceId, + MachineAccessMode, Membership, MembershipRole, OperationSecurityLevel, PlatformApiKeyScope, + User, UserId, WorkspaceId, }; #[derive(Clone, Debug, PartialEq, Eq)] @@ -95,6 +95,51 @@ impl MachineTokenIssuer for NoMachineTokenIssuer { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum IdentityProviderKind { + Password, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct AuthenticatedIdentity { + pub user: User, + pub memberships: Vec, + pub current_workspace_id: Option, +} + +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum IdentityError { + #[error("not supported for this provider")] + NotSupportedForProvider, + #[error("bad credentials")] + BadCredentials, + #[error("account disabled")] + AccountDisabled, + #[error("internal: {0}")] + Internal(String), +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct LoginPayload { + pub email: String, + pub password: String, +} + +pub enum LoginOutcome { + Authenticated(AuthenticatedIdentity), +} + +#[async_trait] +pub trait IdentityProvider: Send + Sync { + fn id(&self) -> &str; + + fn kind(&self) -> IdentityProviderKind; + + async fn login_password(&self, payload: LoginPayload) -> Result; +} + +pub type SharedIdentityProvider = Arc; + #[cfg(test)] mod tests { use super::{MachineTokenIssuer, NoMachineTokenIssuer, TokenIssuerActor, TokenIssuerError}; diff --git a/crates/crank-core/src/lib.rs b/crates/crank-core/src/lib.rs index da15678..5c57c25 100644 --- a/crates/crank-core/src/lib.rs +++ b/crates/crank-core/src/lib.rs @@ -40,9 +40,10 @@ pub use ext::audit::{ AuditTargetKind, NoopAuditSink, SharedAuditSink, }; pub use ext::auth::{ - MachineCredentialVerifier, MachineCredentialVerifierError, MachineTokenIssuer, - NoMachineTokenIssuer, SharedMachineCredentialVerifier, SharedMachineTokenIssuer, - TokenIssuerActor, TokenIssuerError, VerifiedMachineCredential, + AuthenticatedIdentity, IdentityError, IdentityProvider, IdentityProviderKind, LoginOutcome, + LoginPayload, MachineCredentialVerifier, MachineCredentialVerifierError, MachineTokenIssuer, + NoMachineTokenIssuer, SharedIdentityProvider, SharedMachineCredentialVerifier, + SharedMachineTokenIssuer, TokenIssuerActor, TokenIssuerError, VerifiedMachineCredential, }; pub use ext::capability::{CapabilityProfile, CommunityCapabilityProfile}; pub use ids::{