Add log schema and documentation
This commit is contained in:
59
docs/LOG.md
Normal file
59
docs/LOG.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Schema LOG
|
||||||
|
|
||||||
|
Log inmutable de mensajes del sistema TZZR.
|
||||||
|
|
||||||
|
## Tabla: log.messages
|
||||||
|
|
||||||
|
Registra todos los mensajes entre usuarios y agentes IA.
|
||||||
|
|
||||||
|
| Campo | Tipo | Descripción |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| id | BIGSERIAL | Índice incremental |
|
||||||
|
| hash | CHAR(64) | SHA256 único del mensaje |
|
||||||
|
| session_hash | CHAR(64) | SHA256 de la sesión |
|
||||||
|
| sender_type | ENUM | Tipo de emisor: user, agent, orchestrator, system, tool |
|
||||||
|
| sender_id | CHAR(64) | Hash del emisor (referencia a players) |
|
||||||
|
| receiver_type | ENUM | Tipo de receptor: user, agent, orchestrator, system, tool |
|
||||||
|
| receiver_id | CHAR(64) | Hash del receptor (referencia a players) |
|
||||||
|
| leader_id | CHAR(64) | Hash del coordinador en multiagente (nullable) |
|
||||||
|
| role | TEXT | Rol del emisor en el contexto |
|
||||||
|
| content | TEXT | Contenido del mensaje |
|
||||||
|
| attachments | JSONB | Adjuntos (archivos, datos) |
|
||||||
|
| prev_hash | CHAR(64) | Hash del mensaje anterior (cadena de integridad) |
|
||||||
|
| context_hashes | CHAR(64)[] | Hashes de mensajes incluidos como contexto |
|
||||||
|
| hashtags | CHAR(64)[] | Hashes de etiquetas asociadas |
|
||||||
|
| created_at | TIMESTAMPTZ | Timestamp de creación |
|
||||||
|
|
||||||
|
## Inmutabilidad
|
||||||
|
|
||||||
|
- **INSERT**: Permitido
|
||||||
|
- **UPDATE**: Bloqueado por trigger
|
||||||
|
- **DELETE**: Bloqueado por trigger
|
||||||
|
|
||||||
|
## Cadena de integridad
|
||||||
|
|
||||||
|
Cada mensaje referencia al anterior via `prev_hash`:
|
||||||
|
|
||||||
|
```
|
||||||
|
msg1.hash = SHA256(msg1)
|
||||||
|
msg2.prev_hash = msg1.hash
|
||||||
|
msg2.hash = SHA256(msg2)
|
||||||
|
msg3.prev_hash = msg2.hash
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Primer mensaje de sesión: `prev_hash = NULL`
|
||||||
|
|
||||||
|
## Índices
|
||||||
|
|
||||||
|
- `session_hash` - Buscar mensajes de una sesión
|
||||||
|
- `sender_id` - Mensajes enviados por un actor
|
||||||
|
- `receiver_id` - Mensajes recibidos por un actor
|
||||||
|
- `prev_hash` - Seguir cadena de integridad
|
||||||
|
- `created_at` - Ordenar cronológicamente
|
||||||
|
- `hashtags` (GIN) - Buscar por etiquetas
|
||||||
|
|
||||||
|
## Relaciones externas
|
||||||
|
|
||||||
|
- `sender_id` y `receiver_id` referencian hashes de `core.players`
|
||||||
|
- `hashtags` referencian hashes de `core.hashtags`
|
||||||
76
schemas/04_log.sql
Normal file
76
schemas/04_log.sql
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- SCHEMA LOG - Sistema TZZR
|
||||||
|
-- Log inmutable de mensajes
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
DROP SCHEMA IF EXISTS log CASCADE;
|
||||||
|
CREATE SCHEMA log;
|
||||||
|
|
||||||
|
-- Extensiones
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||||
|
|
||||||
|
-- Tipos
|
||||||
|
CREATE TYPE log.actor_type AS ENUM ('user', 'agent', 'orchestrator', 'system', 'tool');
|
||||||
|
|
||||||
|
-- Tabla principal
|
||||||
|
CREATE TABLE log.messages (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
hash CHAR(64) UNIQUE NOT NULL,
|
||||||
|
session_hash CHAR(64) NOT NULL,
|
||||||
|
sender_type log.actor_type NOT NULL,
|
||||||
|
sender_id CHAR(64) NOT NULL,
|
||||||
|
receiver_type log.actor_type NOT NULL,
|
||||||
|
receiver_id CHAR(64) NOT NULL,
|
||||||
|
leader_id CHAR(64),
|
||||||
|
role TEXT,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
attachments JSONB DEFAULT '{}',
|
||||||
|
prev_hash CHAR(64),
|
||||||
|
context_hashes CHAR(64)[] DEFAULT '{}',
|
||||||
|
hashtags CHAR(64)[] DEFAULT '{}',
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Índices
|
||||||
|
CREATE INDEX idx_messages_session ON log.messages(session_hash);
|
||||||
|
CREATE INDEX idx_messages_sender ON log.messages(sender_id);
|
||||||
|
CREATE INDEX idx_messages_receiver ON log.messages(receiver_id);
|
||||||
|
CREATE INDEX idx_messages_prev ON log.messages(prev_hash);
|
||||||
|
CREATE INDEX idx_messages_created ON log.messages(created_at);
|
||||||
|
CREATE INDEX idx_messages_hashtags ON log.messages USING gin(hashtags);
|
||||||
|
|
||||||
|
-- Función SHA256
|
||||||
|
CREATE OR REPLACE FUNCTION log.sha256(data TEXT) RETURNS CHAR(64) AS $$
|
||||||
|
BEGIN
|
||||||
|
RETURN encode(digest(data, 'sha256'), 'hex');
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
|
-- Protección: no UPDATE
|
||||||
|
CREATE OR REPLACE FUNCTION log.prevent_update() RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'UPDATE no permitido en log.messages';
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Protección: no DELETE
|
||||||
|
CREATE OR REPLACE FUNCTION log.prevent_delete() RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
RAISE EXCEPTION 'DELETE no permitido en log.messages';
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Triggers de protección
|
||||||
|
CREATE TRIGGER protect_update BEFORE UPDATE ON log.messages
|
||||||
|
FOR EACH ROW EXECUTE FUNCTION log.prevent_update();
|
||||||
|
|
||||||
|
CREATE TRIGGER protect_delete BEFORE DELETE ON log.messages
|
||||||
|
FOR EACH ROW EXECUTE FUNCTION log.prevent_delete();
|
||||||
|
|
||||||
|
-- Permisos
|
||||||
|
GRANT USAGE ON SCHEMA log TO tzzr;
|
||||||
|
GRANT SELECT, INSERT ON log.messages TO tzzr;
|
||||||
|
GRANT USAGE ON SEQUENCE log.messages_id_seq TO tzzr;
|
||||||
|
|
||||||
|
-- Verificación
|
||||||
|
SELECT 'Schema log creado' as status;
|
||||||
Reference in New Issue
Block a user