---
name: session_create
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func SessionCreate(db *sql.DB, userID string, ttl time.Duration, metadata map[string]any) (Session, error)"
description: "Crea una sesion SQLite con token aleatorio de 32 bytes hex (256 bits de entropia). Crea la tabla sessions si no existe. Retorna la Session lista para devolver al cliente."
tags: [session, auth, sqlite, token, infra]
uses_functions: []
uses_types: [Session_go_infra]
returns: [Session_go_infra]
returns_optional: false
error_type: error_go_core
imports: [crypto/rand, database/sql, encoding/hex, encoding/json, fmt, time]
params:
  - name: db
    desc: "conexion SQL abierta a la BD de la app. No debe ser nil"
  - name: userID
    desc: "identificador del usuario al que pertenece la sesion. No vacio"
  - name: ttl
    desc: "tiempo de vida de la sesion (time.Duration). Debe ser positivo"
  - name: metadata
    desc: "datos libres a persistir junto a la sesion (role, email, ip, etc.). Puede ser nil"
output: "Session con token opaco listo para devolver al cliente via header o cookie"
tested: true
tests: ["crea sesion y persiste en BD", "genera tokens distintos", "rechaza db nil", "rechaza user_id vacio"]
test_file_path: "functions/infra/session_test.go"
file_path: "functions/infra/session_create.go"
---

## Ejemplo

```go
db, _ := sql.Open("sqlite3", "app.db")
session, err := SessionCreate(db, user.ID, 24*time.Hour, map[string]any{
    "email": user.Email,
    "role":  "admin",
    "ip":    r.RemoteAddr,
})
if err != nil {
    HTTPErrorResponse(w, HTTPError{Status: 500, Code: "session_error", Message: err.Error()})
    return
}
HTTPJSONResponse(w, 200, map[string]string{"token": session.Token})
```

## Notas

Impura — hace I/O en SQLite, usa entropia del OS con `crypto/rand`, y lee el tiempo con `time.Now()`. La tabla `sessions` se crea con `CREATE TABLE IF NOT EXISTS` (PK token, indices en user_id y expires_at) para que la primera llamada deje todo listo sin setup manual. Token es 32 bytes aleatorios codificados en hex = 64 chars, 256 bits de entropia. Session fixation mitigada: el token lo genera el servidor, no se acepta del cliente. Para invalidar una sesion: `DELETE FROM sessions WHERE token = ?`. Limpieza periodica de expiradas: SessionCleanup.
