Skip to content

auth

import "github.com/neochaotic/leoflow/internal/auth"

Package auth provides JWT authentication, password hashing, the RBAC permission model, and login rate limiting for the control plane (ADR 0008).

Index

Variables

ErrInvalidCredentials is returned when a username/password pair is rejected.

var ErrInvalidCredentials = errors.New("invalid credentials")

ErrInvalidToken is returned when a token is malformed, expired, or unsigned by us.

var ErrInvalidToken = errors.New("invalid token")

func HashPassword

func HashPassword(password string) (string, error)

HashPassword hashes a plaintext password with bcrypt.

func MintUserToken

func MintUserToken(secret string, ttl time.Duration, user User) (string, error)

MintUserToken signs a user JWT directly, without checking credentials against a store. It is for trusted in-process callers only โ€” notably `leoflow dev`, which runs its own control plane and must register DAGs without a login round-trip. The token validates under Authenticate using the same secret.

func VerifyPassword

func VerifyPassword(hash, password string) bool

VerifyPassword reports whether password matches the stored bcrypt hash.

type AgentIdentity

AgentIdentity is the task instance a verified agent token represents.

type AgentIdentity struct {
    TaskInstanceID string
    TenantID       string
    DagID          string
    RunID          string
    TaskID         string
    TryNumber      int
}

type Authenticator

Authenticator issues and validates authentication tokens. The MVP ships a JWT implementation; the interface keeps OIDC/LDAP pluggable (ADR 0008).

type Authenticator interface {
    Authenticate(ctx context.Context, token string) (*User, error)
    IssueToken(ctx context.Context, creds Credentials) (string, error)
}

type Credentials

Credentials are the inputs to token issuance.

type Credentials struct {
    Tenant   string
    Username string
    Password string
}

type JWTAuthenticator

JWTAuthenticator issues and validates HS256 JWTs against a UserStore.

type JWTAuthenticator struct {
    // contains filtered or unexported fields
}

func NewJWTAuthenticator

func NewJWTAuthenticator(store UserStore, secret string, ttl time.Duration) *JWTAuthenticator

NewJWTAuthenticator builds a JWTAuthenticator with the given user store, HS256 secret, and token lifetime.

func (*JWTAuthenticator) Authenticate

func (a *JWTAuthenticator) Authenticate(_ context.Context, token string) (*User, error)

Authenticate validates a bearer token and reconstructs the user from its claims.

func (*JWTAuthenticator) AuthenticateAgent

func (a *JWTAuthenticator) AuthenticateAgent(token string) (*AgentIdentity, error)

AuthenticateAgent validates an agent bearer token and returns the task instance it identifies.

func (*JWTAuthenticator) IssueAgentToken

func (a *JWTAuthenticator) IssueAgentToken(id AgentIdentity, ttl time.Duration) (string, error)

IssueAgentToken mints a signed token that identifies a single task instance, valid for the given TTL. The control plane passes it to the worker pod.

func (*JWTAuthenticator) IssueToken

func (a *JWTAuthenticator) IssueToken(ctx context.Context, creds Credentials) (string, error)

IssueToken validates the credentials against the store and returns a signed JWT.

type Permission

Permission is an action on a resource (e.g. {Action: "read", Resource: "dag"}).

type Permission struct {
    Action   string `json:"action"`
    Resource string `json:"resource"`
}

type RateLimiter

RateLimiter is a per-key fixed-window limiter used to throttle failed logins per client IP (ADR 0008).

type RateLimiter struct {
    // contains filtered or unexported fields
}

func NewRateLimiter

func NewRateLimiter(limit int, window time.Duration) *RateLimiter

NewRateLimiter builds a limiter allowing limit events per window per key.

func (*RateLimiter) Allow

func (r *RateLimiter) Allow(key string) bool

Allow records an event for key and reports whether it is within the limit.

func (*RateLimiter) Blocked

func (r *RateLimiter) Blocked(key string) bool

Blocked reports whether key has already reached its limit in the current window, WITHOUT recording an attempt (a peek). The login handler uses it to reject an over-limit caller up front while calling Allow only for actual failures โ€” so a successful login never consumes the budget and a user who mistypes a few times is not locked out the moment they finally get it right.

type User

User is an authenticated principal with its tenant, roles, and permissions.

type User struct {
    ID          string
    TenantID    string
    Email       string
    Roles       []string
    Permissions []Permission
}

func (*User) HasPermission

func (u *User) HasPermission(action, resource string) bool

HasPermission reports whether the user may perform action on resource. The admin role, or an admin action / wildcard resource permission, grants access.

type UserStore

UserStore loads users for authentication. storage implements it.

type UserStore interface {
    FindUserByLogin(ctx context.Context, tenant, username string) (user *User, passwordHash string, err error)
}

Generated by gomarkdoc