- pnpm monorepo: apps/api (Fastify + SQLite + SSE), apps/web (React+Vite), packages/shared, packages/pi-adapter - Local auth (admin/webhook-runner roles) + Keycloak JWT ready - Multi-session chat with reliable history (user persisted before LLM, assistant persisted after stream) - Markdown knowledge base with /api/docs/search + /api/docs/:id - YAML webhook catalog with backend-only execution, retry/backoff, audit (webhook_runs), and per-user rate limit - Skills config (sre-on-call, blameless-postmortem, security-incident) injected into LLM system prompt - LLM provider failover chain (config/models.yml fallback + LLM_FALLBACK_CHAIN override) - Context-aware webhooks panel + backend id-mention safety net - Per-message stats (time/duration/tokens/model), Markdown+GFM render, code & table copy/download buttons - Vitest suite, end-to-end smoke test (scripts/smoke.mjs), per-session system prompt override - /metrics Prometheus endpoint + /api/metrics JSON, request-id correlation - dotenv with explicit repo-root path; envString/envNumber helpers (handles empty-string env) - Runbooks + SOPs under knowledge/ in English; README, docs, and INDEX.md in English
58 lines
1.4 KiB
Markdown
58 lines
1.4 KiB
Markdown
# Reliable History
|
|
|
|
## Goal
|
|
|
|
Guarantee that the chat history is reconstructible, isolated by user, and consistent even if the backend restarts.
|
|
|
|
## Mandatory rules
|
|
|
|
1. Persist the user message before calling the LLM.
|
|
2. Persist the assistant response when the stream finishes.
|
|
3. If the LLM fails, record the failure in metadata or as a controlled error message.
|
|
4. Do not keep critical conversational state in memory.
|
|
5. All session and message queries must filter by `session_id` AND `user_id`.
|
|
6. Webhooks must be audited even when they fail.
|
|
|
|
## Base tables
|
|
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS chat_sessions (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
title TEXT,
|
|
created_at TEXT NOT NULL,
|
|
updated_at TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS chat_messages (
|
|
id TEXT PRIMARY KEY,
|
|
session_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
role TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
metadata TEXT,
|
|
created_at TEXT NOT NULL,
|
|
FOREIGN KEY (session_id) REFERENCES chat_sessions(id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS webhook_runs (
|
|
id TEXT PRIMARY KEY,
|
|
webhook_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
session_id TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
request_payload TEXT,
|
|
response_status INTEGER,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
```
|
|
|
|
## Security invariant
|
|
|
|
```sql
|
|
WHERE session_id = ?
|
|
AND user_id = ?
|
|
```
|
|
|
|
Without this filter, the query is incorrectly designed.
|