# Authentication Architecture

## System Overview

```
┌─────────────────────────────────────────────────────────────────┐
│                         HTTP Layer (Hono)                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │   Register   │  │    Login     │  │   Logout     │          │
│  │ POST /register│  │ POST /login  │  │POST /logout  │          │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘          │
│         │                  │                  │                   │
│         │                  │                  │  ┌──────────────┐│
│         │                  │                  │  │     Me       ││
│         │                  │                  │  │  GET /me     ││
│         │                  │                  │  └──────┬───────┘│
│         │                  │                  │         │        │
│         └──────────────────┴──────────────────┴─────────┘        │
│                              │                                    │
└──────────────────────────────┼────────────────────────────────────┘
                               │
                    ┌──────────▼──────────┐
                    │   authMiddleware    │
                    │  Token Extraction   │
                    │  Token Verification │
                    │  Context Injection  │
                    └──────────┬──────────┘
                               │
┌──────────────────────────────┼────────────────────────────────────┐
│                    Effect-TS Service Layer                        │
├──────────────────────────────┼────────────────────────────────────┤
│                               │                                    │
│                    ┌──────────▼──────────┐                        │
│                    │    AuthService      │                        │
│                    │  - register()       │                        │
│                    │  - login()          │                        │
│                    │  - logout()         │                        │
│                    │  - verifyToken()    │                        │
│                    └─────────┬───────────┘                        │
│                              │                                     │
│         ┌────────────────────┼────────────────────┐               │
│         │                    │                    │               │
│  ┌──────▼─────┐    ┌────────▼────────┐   ┌──────▼──────┐        │
│  │ Password   │    │  TokenService   │   │   Audit     │        │
│  │  Service   │    │  - generate()   │   │   Service   │        │
│  │  - hash()  │    │  - verify()     │   │  - log()    │        │
│  │  - verify()│    │  - hashToken()  │   └─────────────┘        │
│  └────────────┘    └─────────────────┘                           │
│                                                                   │
│  ┌──────────────┐            ┌──────────────┐                    │
│  │     User     │            │   Session    │                    │
│  │  Repository  │            │  Repository  │                    │
│  │  - create()  │            │  - create()  │                    │
│  │  - findBy*() │            │  - findBy*() │                    │
│  │  - update()  │            │  - revoke()  │                    │
│  └──────┬───────┘            └──────┬───────┘                    │
│         │                           │                             │
└─────────┼───────────────────────────┼─────────────────────────────┘
          │                           │
┌─────────▼───────────────────────────▼─────────────────────────────┐
│                      Database Layer (SQLite)                       │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐               │
│  │    users    │  │  sessions   │  │ audit_logs  │               │
│  │             │  │             │  │             │               │
│  │ • id        │  │ • id        │  │ • id        │               │
│  │ • username  │  │ • user_id   │  │ • user_id   │               │
│  │ • email     │  │ • token_hash│  │ • action    │               │
│  │ • password  │  │ • ip_addr   │  │ • ip_addr   │               │
│  │ • linux_usr │  │ • user_agent│  │ • details   │               │
│  │ • failed    │  │ • expires   │  │ • timestamp │               │
│  └─────────────┘  └─────────────┘  └─────────────┘               │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘
```

## Request Flow

### Registration Flow

```
Client Request
    │
    │ POST /api/auth/register
    │ { username, email, password }
    │
    ▼
┌───────────────────────────────────┐
│       authRoutes.post()           │
│  1. Extract request body          │
│  2. Extract IP, user agent        │
│  3. Call AuthService.register()   │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│    AuthService.register()         │
│  1. Validate username             │
│  2. Validate email                │
│  3. Validate password strength    │
│  4. Check duplicates              │
│  5. Hash password (bcrypt)        │
│  6. Generate linux_username       │
│  7. Create user in DB             │
│  8. Log audit event               │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│      UserRepository.create()      │
│  1. Generate UUID                 │
│  2. Insert into users table       │
│  3. Return user object            │
└───────────────┬───────────────────┘
                │
                ▼
         201 Created
    { user: { id, username, email } }
```

### Login Flow

```
Client Request
    │
    │ POST /api/auth/login
    │ { email, password }
    │
    ▼
┌───────────────────────────────────┐
│       authRoutes.post()           │
│  1. Extract request body          │
│  2. Extract IP, user agent        │
│  3. Call AuthService.login()      │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│     AuthService.login()           │
│  1. Find user by email            │
│  2. Check account lockout         │
│  3. Verify password               │
│  4. Reset/increment failed tries  │
│  5. Update last login time        │
│  6. Create session                │
│  7. Generate JWT token            │
│  8. Log audit event               │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│    TokenService.generateToken()   │
│  1. Create JWT payload            │
│  2. Sign with RS256               │
│  3. Return token string           │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│   SessionRepository.create()      │
│  1. Generate session ID           │
│  2. Hash token with SHA-256       │
│  3. Insert into sessions table    │
│  4. Return session object         │
└───────────────┬───────────────────┘
                │
                ▼
      200 OK + Set-Cookie
    { user: {...}, token: "..." }
```

### Protected Route Flow

```
Client Request
    │
    │ GET /api/auth/me
    │ Authorization: Bearer <token>
    │ OR Cookie: auth_token=<token>
    │
    ▼
┌───────────────────────────────────┐
│      authMiddleware()             │
│  1. Extract token from header     │
│     or cookie                     │
│  2. Call AuthService.verify()     │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│   AuthService.verifyToken()       │
│  1. Verify JWT signature          │
│  2. Check expiration              │
│  3. Hash token                    │
│  4. Find session by hash          │
│  5. Check session not revoked     │
│  6. Find user by ID               │
│  7. Check user is active          │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│      Context Injection            │
│  c.set('user', user)              │
│  c.set('session', session)        │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│       Route Handler               │
│  const user = c.get('user')       │
│  const session = c.get('session') │
│  return c.json({ user })          │
└───────────────┬───────────────────┘
                │
                ▼
           200 OK
      { user: {...} }
```

### Logout Flow

```
Client Request
    │
    │ POST /api/auth/logout
    │ Cookie: auth_token=<token>
    │
    ▼
┌───────────────────────────────────┐
│      authMiddleware()             │
│  1. Verify token                  │
│  2. Inject user & session         │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│       authRoutes.post()           │
│  1. Get session from context      │
│  2. Call AuthService.logout()     │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│    AuthService.logout()           │
│  1. Revoke session                │
│  2. Log audit event               │
└───────────────┬───────────────────┘
                │
                ▼
┌───────────────────────────────────┐
│  SessionRepository.revoke()       │
│  1. Set is_revoked = true         │
│  2. Set revoked_at = now          │
└───────────────┬───────────────────┘
                │
                ▼
    200 OK + Clear Cookie
   { message: "Logged out" }
```

## Effect-TS Dependency Graph

```
┌─────────────────────────────────────────────────────────────────┐
│                           AppLayer                               │
└─────────────────────────────────────────────────────────────────┘
                               │
                               │ Layer.mergeAll()
                ┌──────────────┼──────────────┐
                │              │              │
    ┌───────────▼───────┐  ┌───▼──────┐  ┌───▼─────────┐
    │ DatabaseService   │  │Password  │  │   Token     │
    │     .Live         │  │Service   │  │  Service    │
    └───────────┬───────┘  │ .Live    │  │  .Live      │
                │          └──────────┘  └─────────────┘
                │
                │ Layer.provideMerge()
                │
    ┌───────────▼───────────────────────────────┐
    │  UserRepository.Live                      │
    │  SessionRepository.Live                   │
    │  AuditLogService.Live                     │
    └───────────┬───────────────────────────────┘
                │
                │ Layer.provideMerge()
                │
    ┌───────────▼───────────────────────────────┐
    │         AuthService.Live                  │
    │                                            │
    │  Provides:                                 │
    │  - register()                              │
    │  - login()                                 │
    │  - logout()                                │
    │  - verifyToken()                           │
    └────────────────────────────────────────────┘
```

## Security Architecture

### Password Security

```
Plain Password
     │
     │ validatePasswordStrength()
     │  • Min 8 chars
     │  • Uppercase + Lowercase
     │  • Number required
     │
     ▼
  bcrypt.hash()
     │ salt_rounds=12
     │
     ▼
Password Hash
     │ stored in DB
     │ never logged
     │ never transmitted
```

### Token Security

```
User Login
     │
     ▼
Generate JWT
     │ RS256 Algorithm
     │ Private Key Signing
     │ 7 Day Expiry
     │
     ├─────────────────┬──────────────────┐
     │                 │                  │
     ▼                 ▼                  ▼
  JWT Token      SHA-256 Hash        Session
     │           stored in DB         Record
     │                                    │
     │                                    │
     ▼                                    ▼
Sent to Client              Linked to Token Hash
(httpOnly cookie
 or Bearer token)
```

### Session Validation

```
Incoming Request
     │
     ▼
Extract Token
     │
     ├─── From Authorization Header
     │    "Bearer <token>"
     │
     └─── From Cookie
          "auth_token=<token>"
     │
     ▼
Verify JWT Signature
     │ • Check RS256 signature
     │ • Verify not expired
     │ • Validate payload
     │
     ▼
Hash Token (SHA-256)
     │
     ▼
Find Session by Hash
     │
     ├─── Session not found? → 401
     │
     ├─── Session expired? → 401
     │
     └─── Session revoked? → 401
     │
     ▼
Find User by ID
     │
     └─── User inactive? → 401
     │
     ▼
Request Authorized
```

### Account Lockout

```
Login Attempt
     │
     ▼
Check Failed Attempts
     │
     ├─── >= 5 attempts?
     │         │
     │         ▼
     │    Check Lockout Time
     │         │
     │         ├─── Within 15 min? → LOCKED
     │         │                      Return 401
     │         │
     │         └─── After 15 min? → UNLOCKED
     │                               Continue login
     │
     ▼
Verify Password
     │
     ├─── Invalid?
     │      │
     │      ▼
     │   Increment Failed Attempts
     │   Return 401
     │
     └─── Valid?
            │
            ▼
         Reset Failed Attempts
         Create Session
         Return 200 + Token
```

## Data Flow Patterns

### Effect.gen Pattern

```typescript
// Every operation uses Effect.gen
const operation = Effect.gen(function* () {
  // 1. Acquire dependencies
  const service = yield* ServiceTag;

  // 2. Execute operations with yield*
  const result = yield* service.method();

  // 3. Handle errors with typed failures
  if (errorCondition) {
    return yield* Effect.fail(
      new TypedError("code", "message")
    );
  }

  // 4. Return success value
  return result;
});
```

### Layer Composition

```typescript
// Services declare dependencies
export class MyService extends Context.Tag("MyService")<
  MyService,
  Interface
>() {
  static Live = Layer.effect(
    this,
    Effect.gen(function* () {
      // Acquire dependencies
      const dep1 = yield* Dependency1;
      const dep2 = yield* Dependency2;

      // Provide implementation
      return { method: () => Effect.succeed(value) };
    })
  );
}

// Compose into application layer
export const AppLayer = Layer.mergeAll(
  BaseDep1.Live,
  BaseDep2.Live
).pipe(
  Layer.provideMerge(ServiceA.Live),
  Layer.provideMerge(ServiceB.Live),
  Layer.provideMerge(MyService.Live)
);
```

### Error Handling

```typescript
// HTTP Layer
try {
  const result = await Effect.runPromise(
    Effect.provide(operation, AppLayer)
  );
  return c.json(result, 200);
} catch (error) {
  if (error && typeof error === "object" && "_tag" in error) {
    const typedError = error as { _tag: string; message: string };

    switch (typedError._tag) {
      case "AuthError":
        return c.json({ error: typedError.message }, 401);
      case "ValidationError":
        return c.json({ error: typedError.message }, 400);
      case "DatabaseError":
        return c.json({ error: "Internal error" }, 500);
    }
  }
  return c.json({ error: "Unexpected error" }, 500);
}
```

## Type Safety

### No Type Casting
```typescript
// ❌ NEVER use 'as' type casting
const user = data as User;

// ✅ ALWAYS validate and construct
const user: User = {
  id: row.id,
  username: row.username,
  email: row.email,
  // ... explicit mapping
};
```

### Typed Errors
```typescript
// Define error classes
export class AuthError {
  readonly _tag = "AuthError";
  constructor(
    readonly code: string,
    readonly message: string,
    readonly cause?: unknown
  ) {}
}

// Use in Effect
Effect.gen(function* () {
  if (invalid) {
    return yield* Effect.fail(
      new AuthError("INVALID", "Error message")
    );
  }
});
```

### Effect Return Types
```typescript
// Method signatures specify all error types
readonly login: (
  email: string,
  password: string
) => Effect.Effect<
  { user: User; token: string; session: Session },
  AuthError | DatabaseError
>;
```

## Performance Considerations

### Caching Strategy
- JWT keys cached in memory (keyPair variable)
- Database connection pooling via DatabaseService
- Session lookup by token hash (indexed)
- User lookup by email/username (indexed)

### Concurrency
- Independent operations in routes can be parallelized
- Effect composition enables optimal concurrency
- Database operations are sequential by necessity

### Token Hashing
- SHA-256 for fast session lookup
- bcrypt (12 rounds) for password security
- Balance between security and performance
