didi-lot2-backend/backend/DEPLOY_FROM_SCRATCH.md
2026-07-10 03:39:53 -07:00

1649 lines
54 KiB
Markdown

# DIDI Backend - Deploy From Scratch (Full Guide)
Acest document descrie TOTUL necesar pentru a ridica platforma DIDI de la zero pe o masina noua.
---
## CUPRINS
1. [Prerequisite](#1-prerequisite)
2. [Arhitectura serviciilor](#2-arhitectura-serviciilor)
3. [Ordinea de deploy (graf dependente)](#3-ordinea-de-deploy)
4. [ETAPA 0: Pregatire masina](#etapa-0-pregatire-masina)
5. [ETAPA 1: Docker network](#etapa-1-docker-network)
6. [ETAPA 2: PostgreSQL cluster extern](#etapa-2-postgresql-cluster-extern)
7. [ETAPA 3: Data Layer (Redis + RabbitMQ + MinIO + pgAdmin)](#etapa-3-data-layer)
8. [ETAPA 4: Keycloak (autentificare)](#etapa-4-keycloak)
9. [ETAPA 5: Kong (API gateway)](#etapa-5-kong)
10. [ETAPA 6: didiFramework (CRUD parametri)](#etapa-6-didiframework)
11. [ETAPA 7: Sync Redis (populare config)](#etapa-7-sync-redis)
12. [ETAPA 8: agent-v3 + workeri](#etapa-8-agent-v3)
13. [ETAPA 9: Admin Dashboard](#etapa-9-admin-dashboard)
14. [ETAPA 10: Verificare finala](#etapa-10-verificare-finala)
15. [Anexa A: Toate variabilele de mediu](#anexa-a-variabile-de-mediu)
16. [Anexa B: Chei Redis complete](#anexa-b-chei-redis)
17. [Anexa C: Schema PostgreSQL completa](#anexa-c-schema-postgresql)
18. [Anexa D: Date seed necesare](#anexa-d-date-seed)
19. [Anexa E: Servicii externe (GPU, API keys)](#anexa-e-servicii-externe)
20. [Anexa F: Porturi utilizate](#anexa-f-porturi)
---
## 1. Prerequisite
### Software necesar pe masina host
```
Docker Engine >= 24.x
Docker Compose v2 (plugin)
git
curl
psql (client PostgreSQL, pentru initializare DB)
mc (MinIO Client, pentru init buckets)
```
### Resurse externe necesare (NU pe aceasta masina)
| Resursa | Adresa | Scop |
|---------|--------|------|
| PostgreSQL Cluster (Patroni/HAProxy) | 10.11.50.167:5000 | Baza de date principala |
| GPU Machine | 10.11.10.17 | Whisper (54300), Web Search (51100), Qwen Vision (14011) |
| Domain Check API | <domain-check-host>:11000 | Analiza domeniu |
### API Keys necesare
| Key | Variabila | Scop |
|-----|-----------|------|
| OpenRouter | OPENROUTER_API_KEY | Modele LLM (Gemini, GPT-4o, Claude) |
| OpenAI | OPENAI_API_KEY | Fallback LLM + Whisper transcriere |
| Groq | GROQ_API_KEY | Fallback LLM + Whisper transcriere |
| M17 Whisper | M17_WHISPER_TOKEN | Transcriere audio primara |
| Anthropic (optional) | ANTHROPIC_API_KEY | Fallback LLM |
| Google (optional) | GOOGLE_API_KEY | Fallback LLM |
---
## 2. Arhitectura serviciilor
```
Internet
|
[Edge Nginx]
|
[Tunel]
|
+------+------+
| Kong | (port 443 SSL)
| Gateway |
+------+------+
|
+----------------+----------------+
| | |
[Keycloak] [agent-v3] [didi-admin]
(auth JWT) (port 24803) (nginx 443/80)
| |
+----------+----------+ |
| | | |
[workers] [aggregator] | [didiFramework]
(rabbitmq) (verdict) | (port 3005)
| | | |
+----------+----+-----+-----+
|
+---------+---------+
| | |
[Redis] [RabbitMQ] [MinIO]
(6379) (5672) (9000)
| | |
+---------+---------+
|
[PostgreSQL Cluster]
(10.11.50.167:5000)
```
### 4 Docker Compose files
| Fisier | Servicii | Locatie |
|--------|----------|---------|
| production/docker-compose.yml | Kong, Keycloak, Redis | production/ |
| data-layer/docker-compose.yml | PostgreSQL local, RabbitMQ, MinIO, pgAdmin, Redis Commander, didi-admin | services/data-layer/ |
| didiFramework/docker-compose.yml | didiFramework | services/orchestration-layer/didiFramework/ |
| agent-v3/docker-compose.yml | agent-v3, 5 worker types, verdict-aggregator (14 containere) | services/orchestration-layer/agent-v3/ |
---
## 3. Ordinea de deploy
```
[1] Docker network (didi-network)
|
+-->[2] PostgreSQL cluster (extern, trebuie sa existe + schemas create)
|
+-->[3a] Redis (didi-cache) ----+
| |
+-->[3b] RabbitMQ --------------+-->[6] didiFramework -->[7] SYNC REDIS
| | |
+-->[3c] MinIO -----------------+ v
| [8] agent-v3 + workeri
+-->[4] Keycloak (necesita PG) |
| v
+-->[5] Kong (necesita PG + Keycloak) [9] Admin Dashboard
```
**REGULA DE AUR**: Nimic nu porneste fara Redis + PostgreSQL + didi-network.
---
## ETAPA 0: Pregatire masina
```bash
#!/bin/bash
# === ETAPA 0: Pregatire ===
# 0.1 Clone repo
cd /home/admin365
git clone <repo-url> didi_mono
cd didi_mono/backend
# 0.2 Creeaza volume externe Docker (persistenta intre recreari)
docker volume create didi-staging-postgres-data
docker volume create didi-staging-minio-data
docker volume create didi-staging-pgadmin-data
# 0.3 Verifica conectivitate la PostgreSQL cluster
psql -h 10.11.50.167 -p 5000 -U bos_interface -d DIDI -c "SELECT 1;"
# Parola: interface
# 0.4 Verifica conectivitate la GPU machine
curl -s http://10.11.10.17:54300/health && echo "Whisper OK"
curl -s http://10.11.10.17:51100/health && echo "Web Search OK"
curl -s http://10.11.10.17:14011/health && echo "Qwen Vision OK"
```
---
## ETAPA 1: Docker network
```bash
# === ETAPA 1: Creare retea Docker partajata ===
docker network create didi-network
# Verificare
docker network ls | grep didi-network
```
**IMPORTANT**: Toate docker-compose-urile refera `didi-network` ca `external: true`. Daca nu exista, nimic nu porneste.
---
## ETAPA 2: PostgreSQL cluster extern
### 2.1 Creare baze de date si useri
Conecteaza-te la clusterul Patroni ca superuser:
```bash
psql -h 10.11.50.167 -p 5000 -U postgres
```
```sql
-- Baza de date principala DIDI
CREATE DATABASE "DIDI" OWNER bos_interface;
-- Baza de date Kong
CREATE USER kong WITH PASSWORD 'kong123';
CREATE DATABASE kong_db OWNER kong;
GRANT ALL PRIVILEGES ON DATABASE kong_db TO kong;
-- Baza de date Keycloak
CREATE USER keycloak WITH PASSWORD 'keycloak123';
CREATE DATABASE keycloak_db OWNER keycloak;
GRANT ALL PRIVILEGES ON DATABASE keycloak_db TO keycloak;
-- User principal DIDI
CREATE USER bos_interface WITH PASSWORD 'interface';
GRANT ALL PRIVILEGES ON DATABASE "DIDI" TO bos_interface;
```
### 2.2 Creare scheme in baza DIDI
```bash
psql -h 10.11.50.167 -p 5000 -U bos_interface -d DIDI
```
```sql
-- Cele 4 scheme
CREATE SCHEMA IF NOT EXISTS bos_analysis;
CREATE SCHEMA IF NOT EXISTS bos_parammgmt;
CREATE SCHEMA IF NOT EXISTS bos_sysadmin;
CREATE SCHEMA IF NOT EXISTS bos_subscriber;
-- Search path default
ALTER USER bos_interface SET search_path TO bos_parammgmt, bos_analysis, bos_sysadmin, bos_subscriber, public;
```
### 2.3 Creare tabele bos_analysis (6 tabele + 1 view)
```sql
-- === SCHEMA: bos_analysis ===
-- Scrisa de agent-v3, citita de didiFramework (history)
SET search_path TO bos_analysis;
CREATE TABLE IF NOT EXISTS analysis_session (
session_id TEXT PRIMARY KEY,
user_id TEXT,
user_email TEXT,
input_type TEXT, -- text, url, image, audio, video
input_text TEXT,
input_url TEXT,
input_media_url TEXT,
input_hash TEXT, -- SHA256 deduplicare
status TEXT DEFAULT 'pending', -- pending, running, completed, failed
components_run TEXT[],
components_skipped TEXT[],
risk_score NUMERIC,
risk_category TEXT,
risk_level TEXT,
confidence NUMERIC,
confidence_level TEXT,
started_at TIMESTAMP,
completed_at TIMESTAMP,
total_duration_ms INTEGER,
scenario_applied TEXT,
topic_applied TEXT,
source_app TEXT DEFAULT 'web',
api_version TEXT DEFAULT 'v3',
llm_usage JSONB, -- migration 004
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS analysis_techniques (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
manipulation_score NUMERIC,
total_severity NUMERIC,
dimensions_affected TEXT[],
techniques_count INTEGER,
techniques_detected JSONB,
coupling_context JSONB,
llm_screening TEXT,
llm_deep TEXT,
screening_duration_ms INTEGER,
deep_analysis_duration_ms INTEGER,
total_duration_ms INTEGER,
fallbacks_screening INTEGER DEFAULT 0,
fallbacks_deep INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS analysis_ai_tampered (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
ai_probability NUMERIC,
verdict TEXT,
risk_score NUMERIC,
categories_affected TEXT[],
indicators_count INTEGER,
disclosure_detected BOOLEAN,
disclosure_explicit BOOLEAN,
disclosure_text TEXT,
indicators_detected JSONB,
coupling_context JSONB,
llm_screening TEXT,
llm_deep TEXT,
screening_duration_ms INTEGER,
deep_analysis_duration_ms INTEGER,
total_duration_ms INTEGER,
fallbacks_screening INTEGER DEFAULT 0,
fallbacks_deep INTEGER DEFAULT 0,
content_type TEXT,
image_analysis JSONB
);
CREATE TABLE IF NOT EXISTS analysis_claims (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
total_claims INTEGER,
verified_true INTEGER,
verified_false INTEGER,
unverified INTEGER,
opinions INTEGER,
credibility_score NUMERIC,
interpretation TEXT,
claims_by_status JSONB,
claims_by_type JSONB,
claims_verified JSONB,
llm_extraction TEXT,
llm_verification TEXT,
extraction_duration_ms INTEGER,
verification_duration_ms INTEGER,
total_duration_ms INTEGER,
web_searches_made INTEGER
);
CREATE TABLE IF NOT EXISTS analysis_domain (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
domain TEXT,
verdict TEXT,
trust_score NUMERIC,
risk_level TEXT,
age_days INTEGER,
age_category TEXT,
domain_created_at TIMESTAMP,
is_blacklisted BOOLEAN,
reputation_score NUMERIC,
has_ssl BOOLEAN,
ssl_valid BOOLEAN,
ssl_issuer TEXT,
registrar TEXT,
organization TEXT,
country TEXT,
red_flags TEXT[],
warnings TEXT[],
duration_ms INTEGER
);
CREATE TABLE IF NOT EXISTS analysis_source_assessment (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
trust_score NUMERIC,
verdict TEXT,
risk_level TEXT,
publication JSONB,
author JSONB,
platform JSONB,
domain JSONB,
formula JSONB,
warnings TEXT[],
red_flags TEXT[],
llm_model TEXT,
duration_ms INTEGER
);
CREATE INDEX IF NOT EXISTS idx_source_assessment_trust_score ON analysis_source_assessment(trust_score);
CREATE INDEX IF NOT EXISTS idx_source_assessment_verdict ON analysis_source_assessment(verdict);
CREATE TABLE IF NOT EXISTS analysis_verdict (
session_id TEXT PRIMARY KEY REFERENCES analysis_session(session_id) ON DELETE CASCADE,
risk_score NUMERIC,
risk_category TEXT,
risk_category_color TEXT,
risk_level TEXT,
risk_level_color TEXT,
severity TEXT,
recommended_action TEXT,
confidence NUMERIC,
confidence_level TEXT,
score_manipulation NUMERIC,
score_claims NUMERIC,
score_ai NUMERIC,
score_source NUMERIC,
score_context NUMERIC,
applied_weights JSONB,
override_applied BOOLEAN,
override_type TEXT,
override_reason TEXT,
override_adjustment NUMERIC,
context_summary JSONB,
components_used TEXT[],
weights_source TEXT,
duration_ms INTEGER,
explanation_ro TEXT, -- migration 001
explanation_en TEXT, -- migration 001
virality_score NUMERIC,
virality_level TEXT,
virality_factors JSONB
);
-- View lightweight (fara JSONB-uri grele)
CREATE OR REPLACE VIEW v_analysis_full AS
SELECT
s.session_id, s.user_id, s.user_email, s.input_type,
s.input_text, s.input_url, s.input_media_url, s.status,
s.components_run, s.components_skipped,
s.risk_score, s.risk_category, s.risk_level,
s.confidence, s.confidence_level,
s.started_at, s.completed_at, s.total_duration_ms,
s.scenario_applied, s.topic_applied,
s.source_app, s.api_version, s.created_at,
-- Verdict
v.risk_score AS verdict_risk_score, v.risk_category AS verdict_risk_category,
v.risk_level AS verdict_risk_level, v.severity, v.recommended_action,
v.confidence AS verdict_confidence, v.confidence_level AS verdict_confidence_level,
v.score_manipulation, v.score_claims, v.score_ai, v.score_source, v.score_context,
v.override_applied, v.override_type, v.weights_source,
v.explanation_ro, v.explanation_en,
v.virality_score, v.virality_level,
-- Techniques (sumar)
t.manipulation_score, t.total_severity, t.dimensions_affected, t.techniques_count,
t.llm_screening AS tech_llm_screening, t.llm_deep AS tech_llm_deep,
t.total_duration_ms AS tech_duration_ms,
-- AI Tampered (sumar)
a.ai_probability, a.verdict AS ai_verdict, a.risk_score AS ai_risk_score,
a.categories_affected AS ai_categories, a.indicators_count AS ai_indicators_count,
a.disclosure_detected, a.content_type AS ai_content_type,
a.total_duration_ms AS ai_duration_ms,
-- Claims (sumar)
c.total_claims, c.verified_true, c.verified_false, c.unverified, c.opinions,
c.credibility_score, c.interpretation AS claims_interpretation,
c.web_searches_made, c.total_duration_ms AS claims_duration_ms,
-- Domain (sumar)
d.domain, d.trust_score AS domain_trust_score, d.verdict AS domain_verdict,
d.risk_level AS domain_risk_level, d.is_blacklisted,
d.duration_ms AS domain_duration_ms,
-- Source Assessment (sumar)
sa.trust_score AS sa_trust_score, sa.verdict AS sa_verdict,
sa.risk_level AS sa_risk_level,
sa.duration_ms AS sa_duration_ms
FROM bos_analysis.analysis_session s
LEFT JOIN bos_analysis.analysis_verdict v ON s.session_id = v.session_id
LEFT JOIN bos_analysis.analysis_techniques t ON s.session_id = t.session_id
LEFT JOIN bos_analysis.analysis_ai_tampered a ON s.session_id = a.session_id
LEFT JOIN bos_analysis.analysis_claims c ON s.session_id = c.session_id
LEFT JOIN bos_analysis.analysis_domain d ON s.session_id = d.session_id
LEFT JOIN bos_analysis.analysis_source_assessment sa ON s.session_id = sa.session_id
ORDER BY s.created_at DESC;
```
### 2.4 Creare tabele bos_parammgmt (~40 tabele)
```sql
-- === SCHEMA: bos_parammgmt ===
-- Scrisa de didiFramework CRUD, sincronizata in Redis
SET search_path TO bos_parammgmt;
-- Tabel parinte versionare
CREATE TABLE IF NOT EXISTS parameter (
parameter_id SERIAL PRIMARY KEY,
parameter_type TEXT,
valid_from DATE DEFAULT CURRENT_DATE,
valid_to DATE,
created_by TEXT,
updated_by TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Ierarhie tehnici (4 nivele)
CREATE TABLE IF NOT EXISTS dimension (
dimension_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
weight NUMERIC DEFAULT 1.0,
description JSONB,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS subdimension (
subdimension_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
dimension_id INTEGER REFERENCES dimension(dimension_id),
code TEXT UNIQUE NOT NULL,
subdmiension_name TEXT NOT NULL, -- NOTA: typo intentionat (legacy)
weight NUMERIC DEFAULT 1.0,
description JSONB,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS technique (
technique_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
subdimension_id INTEGER REFERENCES subdimension(subdimension_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
severity TEXT,
confidence TEXT,
detectability TEXT,
description JSONB,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS technique_indicator (
indicator_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
technique_id INTEGER REFERENCES technique(technique_id),
name TEXT NOT NULL,
description TEXT,
max_intensity INTEGER DEFAULT 3,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS technique_validation_rule (
rule_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
technique_id INTEGER REFERENCES technique(technique_id),
condition TEXT,
action TEXT,
severity TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
-- Verdict si scoring
CREATE TABLE IF NOT EXISTS verdict_category (
verdict_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
range_min NUMERIC,
range_max NUMERIC,
color TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS risk_mapping (
risk_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
level TEXT UNIQUE NOT NULL,
range_min NUMERIC,
range_max NUMERIC,
color TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS severity_assessment (
severity_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
category TEXT UNIQUE NOT NULL,
range_min NUMERIC,
range_max NUMERIC,
action TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
-- Ponderi
CREATE TABLE IF NOT EXISTS component_weight (
weight_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
manipulation NUMERIC DEFAULT 35,
claims NUMERIC DEFAULT 25,
source NUMERIC DEFAULT 20,
ai NUMERIC DEFAULT 15,
context NUMERIC DEFAULT 5,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS weight_scenario (
scenario_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
topic TEXT,
manipulation NUMERIC,
claims NUMERIC,
source NUMERIC,
ai NUMERIC,
context NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS multiplier (
multiplier_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
multiplier_type TEXT NOT NULL, -- topic, temporal, reach
name TEXT,
condition TEXT,
multiplier_value NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
-- Platforme si surse
CREATE TABLE IF NOT EXISTS platform_modifier (
modifier_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
condition TEXT,
score NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS platform (
platform_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
modifier_id INTEGER REFERENCES platform_modifier(modifier_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
score NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS source_type (
source_type_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
base_score NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS source_credibility (
source_credibility_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
criteria TEXT,
weight NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS domain_age_score (
domain_age_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
age_min INTEGER,
age_max INTEGER,
score NUMERIC,
impact TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS domain_risk_level (
risk_level_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
range_min NUMERIC,
range_max NUMERIC,
level TEXT,
interpretation TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS domain_red_flag (
red_flag_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
condition TEXT,
severity TEXT,
action TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS domain_attribute (
attribute_id SERIAL PRIMARY KEY,
source_type_id INTEGER REFERENCES source_type(source_type_id),
name TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS author_classification (
classification_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
score NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS author_credibility (
credibility_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
name TEXT,
impact NUMERIC,
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS author (
author_id SERIAL PRIMARY KEY,
classification_id INTEGER REFERENCES author_classification(classification_id),
credibility_id INTEGER REFERENCES author_credibility(credibility_id),
name TEXT,
is_active BOOLEAN DEFAULT true
);
-- Claims
CREATE TABLE IF NOT EXISTS claim (
claim_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
status TEXT NOT NULL,
weight NUMERIC,
credibility_weight NUMERIC(3,2), -- migration input_profiles
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS claim_type (
claim_type_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
unverified_weight NUMERIC(3,2), -- migration input_profiles
description TEXT,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS confidence (
confidence_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
level TEXT NOT NULL,
color TEXT,
action_recommendation TEXT,
range_min NUMERIC,
range_max NUMERIC,
is_active BOOLEAN DEFAULT true
);
CREATE TABLE IF NOT EXISTS interpretation (
interpretation_id SERIAL PRIMARY KEY,
parameter_id INTEGER REFERENCES parameter(parameter_id),
range_min NUMERIC,
range_max NUMERIC,
label TEXT,
description TEXT,
is_active BOOLEAN DEFAULT true
);
-- Provideri LLM
CREATE TABLE IF NOT EXISTS llm_provider (
provider_id SERIAL PRIMARY KEY,
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
base_url TEXT,
auth_type TEXT,
rate_limit INTEGER,
api_version TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS llm_model (
model_id SERIAL PRIMARY KEY,
provider_id INTEGER REFERENCES llm_provider(provider_id),
code TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
context_window INTEGER,
cost_per_1k_tokens NUMERIC,
capabilities TEXT[],
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS component_provider_assignment (
assignment_id SERIAL PRIMARY KEY,
component_code TEXT NOT NULL,
provider_id INTEGER REFERENCES llm_provider(provider_id),
model_id INTEGER REFERENCES llm_model(model_id),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS provider_api_key (
key_id SERIAL PRIMARY KEY,
provider_id INTEGER REFERENCES llm_provider(provider_id),
key_encrypted TEXT,
usage_tracking JSONB,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
-- Config componente unificate (migration 002)
CREATE TABLE IF NOT EXISTS component_stage_assignment (
stage_id SERIAL PRIMARY KEY,
component_code TEXT NOT NULL,
stage_code TEXT NOT NULL,
fallback_order INTEGER DEFAULT 0,
provider_id INTEGER REFERENCES llm_provider(provider_id),
model_id INTEGER REFERENCES llm_model(model_id),
temperature NUMERIC DEFAULT 0.1,
max_tokens INTEGER DEFAULT 4096,
timeout_ms INTEGER DEFAULT 60000,
is_enabled BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS component_prompt (
prompt_id SERIAL PRIMARY KEY,
component_code TEXT NOT NULL,
stage_code TEXT NOT NULL,
system_prompt TEXT,
user_template TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(component_code, stage_code)
);
CREATE TABLE IF NOT EXISTS component_config (
config_id SERIAL PRIMARY KEY,
component_code TEXT NOT NULL,
config_key TEXT NOT NULL,
config_value JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(component_code, config_key)
);
-- Profiluri input type (adaugat 2026-03-21)
CREATE TABLE IF NOT EXISTS input_type_profile (
profile_id SERIAL PRIMARY KEY,
input_type TEXT UNIQUE NOT NULL,
component_weights JSONB,
inconclusive_rules JSONB,
disclosure_multipliers JSONB,
confidence_config JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS profile_override_config (
override_id SERIAL PRIMARY KEY,
profile_id INTEGER REFERENCES input_type_profile(profile_id),
override_type TEXT NOT NULL,
is_enabled BOOLEAN DEFAULT true,
config JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Extension API keys
CREATE TABLE IF NOT EXISTS extension_api_key (
key_id SERIAL PRIMARY KEY,
key TEXT UNIQUE NOT NULL,
user_id TEXT NOT NULL,
user_email TEXT,
name TEXT,
usage_count INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
```
### 2.5 Creare tabele bos_sysadmin (5 tabele)
```sql
SET search_path TO bos_sysadmin;
CREATE TABLE IF NOT EXISTS subscription_plan (
plan_id SERIAL PRIMARY KEY,
plan_name TEXT NOT NULL,
plan_type INTEGER UNIQUE NOT NULL,
price NUMERIC DEFAULT 0,
included_credits INTEGER DEFAULT 100,
storage_limit_gb NUMERIC DEFAULT 1,
media_limit_count INTEGER DEFAULT 10,
cost_per_text NUMERIC DEFAULT 1,
cost_per_url NUMERIC DEFAULT 1,
cost_per_image NUMERIC DEFAULT 2,
cost_per_audio NUMERIC DEFAULT 3,
cost_per_video NUMERIC DEFAULT 5,
description TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS internet_user (
internet_user_id SERIAL PRIMARY KEY,
person_id INTEGER,
credits_remained INTEGER DEFAULT 100,
credits_spent INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS user_credential (
credential_id SERIAL PRIMARY KEY,
internet_user_id INTEGER REFERENCES internet_user(internet_user_id),
email TEXT UNIQUE,
keycloak_id TEXT UNIQUE,
enrollment_type TEXT DEFAULT 'keycloak',
subscription_status TEXT DEFAULT 'active',
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS subscription (
subscription_id SERIAL PRIMARY KEY,
internet_user_id INTEGER REFERENCES internet_user(internet_user_id),
subscription_plan_id INTEGER REFERENCES subscription_plan(plan_id),
status TEXT DEFAULT 'active',
activation_date TIMESTAMP DEFAULT NOW(),
expiry_date TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS ai_credit_usage (
usage_id SERIAL PRIMARY KEY,
session_id TEXT,
user_id TEXT,
credits_used NUMERIC DEFAULT 1,
input_type TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
```
### 2.6 Creare tabele bos_subscriber (4 tabele)
```sql
SET search_path TO bos_subscriber;
CREATE TABLE IF NOT EXISTS person (
person_id SERIAL PRIMARY KEY,
person_type TEXT DEFAULT 'F',
status TEXT DEFAULT 'active',
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS address (
address_id SERIAL PRIMARY KEY,
person_id INTEGER REFERENCES person(person_id),
address_type TEXT DEFAULT 'residential',
street TEXT,
city TEXT,
postal_code TEXT,
country TEXT DEFAULT 'RO',
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS persoana_fizica (
pf_id SERIAL PRIMARY KEY,
person_id INTEGER REFERENCES person(person_id),
first_name TEXT,
last_name TEXT,
cnp TEXT,
date_of_birth DATE,
address_id INTEGER REFERENCES address(address_id),
created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS contact (
contact_id SERIAL PRIMARY KEY,
person_id INTEGER REFERENCES person(person_id),
contact_type_id INTEGER DEFAULT 1,
contact_info TEXT,
is_primary BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
```
### 2.7 Seed data obligatoriu
```sql
-- Planuri abonament (obligatoriu pentru auto-inregistrare utilizatori)
SET search_path TO bos_sysadmin;
INSERT INTO subscription_plan (plan_name, plan_type, price, included_credits, storage_limit_gb)
VALUES
('Free', 1, 0, 100, 1),
('Starter', 2, 9.99, 500, 5),
('Basic', 3, 19.99, 1000, 10),
('Pro', 4, 49.99, 5000, 50),
('Business', 5, 99.99, 20000, 100),
('Enterprise', 6, 0, 999999, 1000);
```
**NOTA CRITICA**: Datele din `bos_parammgmt` (dimensiuni, tehnici, indicatori, verdicte, ponderi, platforme, claim statuses, etc.) trebuie populate prin admin dashboard sau import SQL. Fara aceste date, analizele nu functioneaza!
Fisierul cu 166 tehnici: `didiFramework/sql/populate_technique_descriptions.sql`
---
## ETAPA 3: Data Layer
```bash
cd /home/admin365/didi_mono/backend/services/data-layer
# === 3.1 Pornire Redis + RabbitMQ + MinIO + pgAdmin + Redis Commander ===
docker compose up -d staging-dataLayer-rabbitmq staging-dataLayer-minio staging-dataLayer-pgadmin staging-dataLayer-redis-commander
# NOTA: Redis (didi-cache) este in production/docker-compose.yml, NU aici!
cd /home/admin365/didi_mono/backend/production
docker compose up -d didi-cache
# === 3.2 Verificare health ===
# Redis
docker exec didi-cache redis-cli -a redis123 ping
# Raspuns asteptat: PONG
# RabbitMQ
curl -s -u admin:rabbitmq123 http://localhost:15672/api/overview | head -c 100
# Raspuns: JSON cu overview
# MinIO
curl -s http://localhost:9000/minio/health/live
# Raspuns: HTTP 200
# === 3.3 Initializare bucket-uri MinIO ===
# Instaleaza mc (MinIO Client) daca nu exista
# wget https://dl.min.io/client/mc/release/linux-amd64/mc && chmod +x mc && mv mc /usr/local/bin/
mc alias set didi http://localhost:9000 minioadmin minio123
# Ruleaza scriptul de init
cd /home/admin365/didi_mono/backend/services/data-layer/didiStorage
bash init-buckets.sh
# SAU manual:
mc mb didi/uploads didi/text-files didi/image-files didi/audio-files didi/video-files didi/document-files didi/pipeline-artifacts didi/backups --ignore-existing
mc version enable didi/pipeline-artifacts
mc version enable didi/backups
# === 3.4 Initializare cozi RabbitMQ ===
cd /home/admin365/didi_mono/backend/services/data-layer/didiQueue
bash init-queues.sh
# NOTA: Cozile cu prioritati (24 cozi = 4 componente x 6 planuri)
# sunt create DINAMIC de workerii agent-v3 la startup.
# init-queues.sh creeaza doar topologia legacy.
```
### Verificare completa Data Layer
```bash
echo "=== Redis ===" && docker exec didi-cache redis-cli -a redis123 ping
echo "=== RabbitMQ ===" && curl -s -u admin:rabbitmq123 http://localhost:15672/api/overview | python3 -c "import sys,json;print(json.load(sys.stdin)['rabbitmq_version'])"
echo "=== MinIO ===" && mc ls didi/ 2>/dev/null | wc -l && echo "buckets"
```
---
## ETAPA 4: Keycloak
```bash
cd /home/admin365/didi_mono/backend/production
# === 4.1 Pornire Keycloak ===
docker compose up -d keycloak
# Asteptare startup (poate dura 30-60s)
echo "Asteptare Keycloak..."
until curl -sf http://localhost:8080/health/ready 2>/dev/null; do sleep 5; done
echo "Keycloak ready!"
# === 4.2 Import realm (daca e prima pornire) ===
# Keycloak importa automat din /opt/keycloak/data/import/ (montat in docker-compose)
# Fisier: didi-clients-realm.json
# Contine: realm didi-clients, 4 clienti OAuth2, 7 roluri, 4 grupuri, 5 utilizatori
# === 4.3 Verificare ===
curl -s http://localhost:8080/realms/didi-clients | python3 -c "import sys,json;d=json.load(sys.stdin);print(f'Realm: {d[\"realm\"]}')"
# Raspuns: Realm: didi-clients
```
### Utilizatori default Keycloak
| Email | Parola | Grup | Rol |
|-------|--------|------|-----|
| admin@didi.local | admin123 | administrators | admin |
| demo@didi.local | Demo123! | free-users | viewer |
| free@didi.local | password123 | free-users | free_tier |
| paid@didi.local | password123 | paid-users | paid_tier |
| enterprise@didi.local | password123 | enterprise-users | enterprise_tier |
---
## ETAPA 5: Kong
```bash
cd /home/admin365/didi_mono/backend/production
# === 5.1 Build imagine Kong (daca nu exista) ===
cd /home/admin365/didi_mono/backend/services/gateway-auth-layer/didiKong
docker build -t didi-kong:latest .
# === 5.2 Pornire Kong ===
cd /home/admin365/didi_mono/backend/production
docker compose up -d kong
# Asteptare
echo "Asteptare Kong..."
until docker exec $(docker ps -qf name=kong) kong health 2>/dev/null; do sleep 5; done
echo "Kong ready!"
# === 5.3 Verificare rute ===
# In productie (DB mode), Kong citeste din PostgreSQL
# NOTA: Kong staging foloseste declarative mode (kong.yml)
```
---
## ETAPA 6: didiFramework
```bash
# === 6.1 Build imagine ===
cd /home/admin365/didi_mono/backend/services/orchestration-layer/didiFramework
docker build -t didi-framework:latest .
# === 6.2 Pornire ===
docker compose up -d
# === 6.3 Verificare ===
until curl -sf http://localhost:3005/health 2>/dev/null; do sleep 3; done
echo "didiFramework ready!"
# Verificare conectivitate DB
curl -s http://localhost:3005/health/all | python3 -c "import sys,json;print(json.dumps(json.load(sys.stdin),indent=2))"
```
### Variabile de mediu didiFramework (din docker-compose.yml)
```
NODE_ENV=production
PORT=3005
HOST=0.0.0.0
DB_HOST=10.11.50.167
DB_PORT=5000
DB_NAME=DIDI
DB_USER=bos_interface
DB_PASSWORD=interface
DB_SCHEMA=bos_parammgmt
REDIS_HOST=didi-cache
REDIS_PORT=6379
REDIS_PASSWORD=redis123
REDIS_DB=0
MINIO_ENDPOINT=staging-dataLayer-minio
MINIO_PORT=9000
MINIO_USE_SSL=false
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minio123
CORS_ORIGIN=*
```
---
## ETAPA 7: Sync Redis (CRITIC!)
Fara aceasta etapa, agent-v3 nu stie ce tehnici sa detecteze, ce ponderi sa aplice, ce verdicte exista.
```bash
# === 7.1 Populare date framework din admin dashboard sau direct SQL ===
# PREREQUISIT: tabelele din bos_parammgmt trebuie sa aiba date!
# Minimum necesar:
# - dimensions (cel putin 1)
# - subdimensions (cel putin 1)
# - techniques (cel putin 1)
# - verdict_category (RELIABLE, MOSTLY_RELIABLE, MIXED, UNRELIABLE, DISINFORMATION)
# - risk_mapping (VERY_LOW, LOW, MODERATE, HIGH, VERY_HIGH, CRITICAL)
# - severity_assessment (LOW, MEDIUM, HIGH, CRITICAL)
# - component_weight (cel putin 1 set de ponderi)
# - claim statusuri (VT, LT, UV, LF, VF, OP, NV)
# - claim types (EF, VF, RE, SC, QA, CC, PC, OF, VC)
# === 7.2 Trigger sync din PG in Redis ===
curl -X POST http://localhost:3005/api/sync-redis
# Raspuns: { "success": true, "synced": ["techniques", "claims", "verdicts", "weights", "sources", "providers"] }
# === 7.3 Verificare chei Redis ===
docker exec didi-cache redis-cli -a redis123 KEYS "didi:framework:*"
# Trebuie sa vezi:
# didi:framework:manifest
# didi:framework:techniques
# didi:framework:claims
# didi:framework:verdicts
# didi:framework:weights
# didi:framework:sources
# didi:framework:providers
# didi:framework:dimensions_compact
docker exec didi-cache redis-cli -a redis123 KEYS "didi:config:*"
# Trebuie sa vezi:
# didi:config:pipeline:v1:*
# didi:config:techniques:v3:*
# didi:config:ai-tampered:v1:*
# didi:config:claims:v1:*
# didi:config:source-assessment:v1:*
# didi:config:verdict:v1:*
# didi:config:vision:v1:*
```
---
## ETAPA 8: agent-v3
```bash
# === 8.1 Creare fisier .env cu API keys ===
cd /home/admin365/didi_mono/backend/services/orchestration-layer/agent-v3
cat > .env << 'EOF'
M17_WHISPER_TOKEN=<TOKEN_WHISPER>
OPENROUTER_API_KEY=<KEY_OPENROUTER>
OPENAI_API_KEY=<KEY_OPENAI>
GROQ_API_KEY=<KEY_GROQ>
ANTHROPIC_API_KEY=
GOOGLE_API_KEY=
EOF
# === 8.2 Build imagine ===
docker compose build agent-v3
# === 8.3 Pornire TOATE serviciile (1 API + 6 worker types = 14 containere) ===
docker compose up -d
# === 8.4 Verificare ===
until curl -sf http://localhost:24803/api/v3/health 2>/dev/null; do sleep 3; done
echo "agent-v3 ready!"
# Verificare workeri
docker compose ps
# Trebuie sa vezi:
# agent-v3 (1 replica)
# worker-media-preprocess (2 replici)
# worker-techniques (2 replici)
# worker-ai-tampered (2 replici)
# worker-claims (3 replici)
# worker-domain (2 replici)
# verdict-aggregator (2 replici)
```
### Variabile de mediu agent-v3 (partajate de toti workerii)
```
NODE_ENV=production
REDIS_HOST=didi-cache
REDIS_PORT=6379
REDIS_PASSWORD=redis123
RABBITMQ_HOST=staging-dataLayer-rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_USER=admin
RABBITMQ_PASS=rabbitmq123
RABBITMQ_VHOST=/
PG_HOST=10.11.50.167
PG_PORT=5000
PG_DATABASE=DIDI
PG_USER=bos_interface
PG_PASSWORD=interface
MINIO_ENDPOINT=staging-dataLayer-minio:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minio123
FRAMEWORK_API_URL=http://didi-framework:3005
SYNC_API_URL=http://didi-framework:3005/api/sync-analysis
PUBLIC_API_BASE_URL=https://didi365.eu
INTERNAL_MEDIA_URL=http://10.11.10.12:24803
M17_WHISPER_URL=http://10.11.10.17:54300/v1/audio/transcriptions
```
---
## ETAPA 9: Admin Dashboard
```bash
# === 9.1 Build imagine ===
cd /home/admin365/didi_mono/backend/admin-dashboard
docker build -t didi-admin:latest .
# === 9.2 Pornire (definit in data-layer/docker-compose.yml) ===
cd /home/admin365/didi_mono/backend/services/data-layer
docker compose up -d didi-admin
# === 9.3 Verificare ===
curl -sk https://localhost:3000/admin/ | head -c 200
# Raspuns: HTML React app
```
---
## ETAPA 10: Verificare finala
```bash
#!/bin/bash
echo "=========================================="
echo " DIDI Platform - Verificare Completa"
echo "=========================================="
echo ""
echo "--- INFRASTRUCTURE ---"
echo -n "Docker Network: " && docker network inspect didi-network > /dev/null 2>&1 && echo "OK" || echo "FAIL"
echo -n "Redis: " && docker exec didi-cache redis-cli -a redis123 ping 2>/dev/null
echo -n "RabbitMQ: " && curl -sf -u admin:rabbitmq123 http://localhost:15672/api/overview > /dev/null && echo "OK" || echo "FAIL"
echo -n "MinIO: " && curl -sf http://localhost:9000/minio/health/live > /dev/null && echo "OK" || echo "FAIL"
echo -n "PostgreSQL: " && docker exec didi-cache redis-cli -a redis123 ping > /dev/null && echo "OK (via Redis)" || echo "N/A"
echo ""
echo "--- AUTH ---"
echo -n "Keycloak: " && curl -sf http://localhost:8080/realms/didi-clients > /dev/null && echo "OK" || echo "FAIL"
echo -n "Kong: " && curl -sf -k https://localhost:443/ > /dev/null && echo "OK" || echo "FAIL"
echo ""
echo "--- SERVICES ---"
echo -n "didiFramework: " && curl -sf http://localhost:3005/health > /dev/null && echo "OK" || echo "FAIL"
echo -n "agent-v3: " && curl -sf http://localhost:24803/api/v3/health > /dev/null && echo "OK" || echo "FAIL"
echo -n "Admin Dashboard: " && curl -sfk https://localhost:3000/admin/ > /dev/null && echo "OK" || echo "FAIL"
echo ""
echo "--- REDIS CONFIG ---"
REDIS_KEYS=$(docker exec didi-cache redis-cli -a redis123 KEYS "didi:framework:*" 2>/dev/null | wc -l)
echo "Framework keys in Redis: $REDIS_KEYS (min 7 expected)"
CONFIG_KEYS=$(docker exec didi-cache redis-cli -a redis123 KEYS "didi:config:*" 2>/dev/null | wc -l)
echo "Config keys in Redis: $CONFIG_KEYS (min 15 expected)"
echo ""
echo "--- WORKERS ---"
cd /home/admin365/didi_mono/backend/services/orchestration-layer/agent-v3
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null
echo ""
echo "--- TEST ANALIZA ---"
echo "Trimite analiza de test:"
echo 'curl -X POST http://localhost:24803/api/v3/pipeline/analyze -H "Content-Type: application/json" -d "{\"text\": \"Test text for analysis\"}"'
```
---
## Anexa A: Toate variabilele de mediu
### Credentiale baze de date
| Variabila | Valoare | Folosit de |
|-----------|---------|------------|
| PG_HOST / DB_HOST | 10.11.50.167 | agent-v3, didiFramework |
| PG_PORT / DB_PORT | 5000 | agent-v3, didiFramework |
| PG_DATABASE / DB_NAME | DIDI | agent-v3, didiFramework |
| PG_USER / DB_USER | bos_interface | agent-v3, didiFramework |
| PG_PASSWORD / DB_PASSWORD | interface | agent-v3, didiFramework |
| KONG_PG_HOST | 10.11.50.167 | Kong |
| KONG_PG_PORT | 5000 | Kong |
| KONG_PG_USER | kong | Kong |
| KONG_PG_PASSWORD | kong123 | Kong |
| KONG_PG_DATABASE | kong_db | Kong |
| KC_DB_HOST | 10.11.50.167 | Keycloak |
| KC_DB_PORT | 5000 | Keycloak |
| KC_DB_NAME | keycloak_db | Keycloak |
| KC_DB_USER | keycloak | Keycloak |
| KC_DB_PASSWORD | keycloak123 | Keycloak |
### Credentiale servicii
| Variabila | Valoare | Folosit de |
|-----------|---------|------------|
| REDIS_HOST | didi-cache | agent-v3, didiFramework |
| REDIS_PORT | 6379 | agent-v3, didiFramework |
| REDIS_PASSWORD | redis123 | Toate |
| RABBITMQ_HOST | staging-dataLayer-rabbitmq | agent-v3 |
| RABBITMQ_PORT | 5672 | agent-v3 |
| RABBITMQ_USER | admin | agent-v3 |
| RABBITMQ_PASS | rabbitmq123 | agent-v3 |
| MINIO_ENDPOINT | staging-dataLayer-minio(:9000) | agent-v3, didiFramework |
| MINIO_ACCESS_KEY | minioadmin | agent-v3, didiFramework |
| MINIO_SECRET_KEY | minio123 | agent-v3, didiFramework |
| KEYCLOAK_ADMIN | admin | Keycloak |
| KEYCLOAK_ADMIN_PASSWORD | admin123 | Keycloak |
### API Keys (secrete)
| Variabila | Folosit de | Scop |
|-----------|------------|------|
| OPENROUTER_API_KEY | agent-v3 | Modele LLM principale |
| OPENAI_API_KEY | agent-v3 | Fallback LLM + Whisper |
| GROQ_API_KEY | agent-v3 | Fallback LLM + Whisper |
| M17_WHISPER_TOKEN | agent-v3 | Transcriere audio primara |
| ANTHROPIC_API_KEY | agent-v3 | Fallback LLM (optional) |
| GOOGLE_API_KEY | agent-v3 | Fallback LLM (optional) |
### URL-uri servicii
| Variabila | Valoare | Folosit de |
|-----------|---------|------------|
| FRAMEWORK_API_URL | http://didi-framework:3005 | agent-v3 |
| PUBLIC_API_BASE_URL | https://didi365.eu | agent-v3 |
| INTERNAL_MEDIA_URL | http://10.11.10.12:24803 | agent-v3 |
| M17_WHISPER_URL | http://10.11.10.17:54300/v1/audio/transcriptions | agent-v3 |
| KC_HOSTNAME_URL | https://didi365.eu/auth | Keycloak |
---
## Anexa B: Chei Redis complete
### Framework (permanente, scrise de didiFramework sync-redis)
| Cheie | Tip | Ce contine |
|-------|-----|------------|
| didi:framework:manifest | STRING (JSON) | Index categorii + timestamp ultima sincronizare |
| didi:framework:techniques | STRING (JSON) | Ierarhie completa: dimensiuni -> subdimensiuni -> tehnici -> indicatori/reguli |
| didi:framework:claims | STRING (JSON) | Statusuri claim, tipuri, confidence, interpretare |
| didi:framework:verdicts | STRING (JSON) | Categorii verdict + risk mappings + severity |
| didi:framework:weights | STRING (JSON) | Ponderi componente + scenarii + multiplicatori |
| didi:framework:sources | STRING (JSON) | Evaluare surse (platforme, credibilitate, domain) |
| didi:framework:providers | STRING (JSON) | Config provideri LLM |
| didi:framework:dimensions_compact | STRING (JSON) | Lista compacta dimensiuni (pt prompts screening) |
### Config componente (permanente, scrise de sync-redis)
| Cheie | Ce contine |
|-------|------------|
| didi:config:pipeline:v1:component_config | Config executor pipeline + video track weights |
| didi:config:pipeline:v1:session_config | Config sesiune pipeline |
| didi:config:pipeline:v1:verdict_config | Override-uri, synergy, confidence (globale) |
| didi:config:pipeline:v1:input_profiles | 6 profiluri verdict per input type |
| didi:config:techniques:v3:available_models | Modele LLM techniques |
| didi:config:techniques:v3:stage_assignments | Assignments etape techniques (screening/deep) |
| didi:config:techniques:v3:scoring_config | Parametri scoring: count_scaler, severe_threshold |
| didi:config:techniques:v3:dimensions_compact | Dimensiuni compacte techniques |
| didi:config:ai-tampered:v1:available_models | Modele LLM AI tampered |
| didi:config:ai-tampered:v1:stage_assignments | Assignments etape AI tampered |
| didi:config:ai-tampered:v1:scoring_config | Blend weights, disclosure impact, thresholds |
| didi:config:ai-tampered:v1:vision_models | Cascade viziune (Qwen -> Gemini -> GPT-4o) |
| didi:config:claims:v1:available_models | Modele LLM claims |
| didi:config:claims:v1:stage_assignments | Assignments etape claims |
| didi:config:claims:v1:scoring_config | Status weights, unverified behavior |
| didi:config:source-assessment:v1:available_models | Modele source assessment |
| didi:config:source-assessment:v1:scoring_config | Axis weights, verdict thresholds |
| didi:config:source-assessment:v1:prompts:extraction | Prompt extractie metadata sursa |
| didi:config:source-assessment:v1:prompts:evaluation | Prompt evaluare sursa |
| didi:config:verdict:v1:available_models | Modele verdict reviewer |
| didi:config:vision:v1:prompts:extraction | Prompt viziune: extragere text din imagine |
| didi:config:vision:v1:prompts:video_frames | Prompt viziune: analiza cadre video |
| didi:config:vision:v1:prompts:ai_detection | Prompt viziune: detectie AI imagine |
### Sesiuni pipeline (TTL 7 zile, scrise de agent-v3)
| Pattern | Ce contine |
|---------|------------|
| didi:pipeline:{sessionId}:status | Status executie (JSON: PipelineStatus) |
| didi:pipeline:{sessionId}:{component} | Rezultat componenta |
| didi:pipeline:{sessionId}:verdict | Verdict final |
| didi:pipeline:history:entry:{sessionId} | Date intrare istoric |
| didi:pipeline:history:user:{userId} | Sorted set istoric user |
### Media cache (TTL 1 ora, scrise de media-preprocess worker)
| Pattern | Ce contine |
|---------|------------|
| agent:media:{sessionId}:transcript | Transcript audio (Whisper) |
| agent:media:{sessionId}:vision:misinformation | Output Vision frames manipulare |
| agent:media:{sessionId}:vision:ai_detection | Output Vision frames AI |
| agent:media:{sessionId}:merged_text | Transcript + vizual combinat |
| agent:media:{sessionId}:lock | Lock procesare media |
| agent:media:{sessionId}:ready | Semnal finalizare ("1") |
### Rezultate intermediare (TTL 7 zile)
| Pattern | Ce contine |
|---------|------------|
| agent:result:{sessionId}:{component}:{stage} | Rezultat etapa (screening/deep) |
### Coada async (TTL scurt)
| Pattern | TTL | Ce contine |
|---------|-----|------------|
| didi:queue:session:{sessionId} | 24h | Stare fan-in agregare |
| didi:queue:lock:{sessionId}:{component} | 5min | Lock worker componenta |
| didi:queue:aggregator:{sessionId} | 30s | Lock agregator verdict |
### Extensie browser (permanente)
| Pattern | Ce contine |
|---------|------------|
| didi:extension:key:{apiKey} | Cache cheie API extensie |
---
## Anexa C: Schema PostgreSQL completa
### Rezumat
| Schema | Tabele | Scris de | Citit de |
|--------|--------|----------|----------|
| bos_analysis | 7 + 1 view | agent-v3 (pg-adapter.ts) | didiFramework (history.ts) |
| bos_parammgmt | ~43 | didiFramework (CRUD routes) | Sync Redis -> agent-v3 |
| bos_sysadmin | 5 | didiFramework (auth.ts, admin.ts) | agent-v3 (credite) |
| bos_subscriber | 4 | didiFramework (auth.ts) | - |
### Conexiuni
| Serviciu | Host:Port | DB | User/Pass | Schema |
|----------|-----------|-----|-----------|--------|
| agent-v3 | 10.11.50.167:5000 | DIDI | bos_interface/interface | bos_analysis |
| didiFramework | 10.11.50.167:5000 | DIDI | bos_interface/interface | bos_parammgmt, bos_sysadmin, bos_subscriber |
| Kong | 10.11.50.167:5000 | kong_db | kong/kong123 | public |
| Keycloak | 10.11.50.167:5000 | keycloak_db | keycloak/keycloak123 | public |
| Waitlist (local) | staging-dataLayer-postgres:5432 | misinformation_db | postgres/postgres123 | public |
---
## Anexa D: Date seed necesare
### Ce trebuie sa existe in bos_parammgmt INAINTE de prima analiza
| Tabel | Minim | Unde se adauga |
|-------|-------|----------------|
| dimension | 2+ dimensiuni | Admin Dashboard > Framework |
| subdimension | 2+ subdimensiuni | Admin Dashboard > Framework |
| technique | 10+ tehnici | Admin Dashboard > Framework |
| technique_indicator | 1+ per tehnica | Admin Dashboard > Framework |
| verdict_category | 5: RELIABLE, MOSTLY_RELIABLE, MIXED, UNRELIABLE, DISINFORMATION | Admin Dashboard > Framework > Verdicts |
| risk_mapping | 6: VERY_LOW, LOW, MODERATE, HIGH, VERY_HIGH, CRITICAL | Admin Dashboard > Framework > Verdicts |
| severity_assessment | 4: LOW, MEDIUM, HIGH, CRITICAL | Admin Dashboard > Framework > Verdicts |
| component_weight | 1 set default | Admin Dashboard > Framework > Weights |
| claim (status) | 7: VT, LT, UV, LF, VF, OP, NV | Admin Dashboard > Framework > Claims |
| claim_type | 9: EF, VF, RE, SC, QA, CC, PC, OF, VC | Admin Dashboard > Framework > Claims |
### Ce trebuie sa existe in didi:config:* Redis
| Cheie | Cum se populeaza | Obligatoriu? |
|-------|------------------|-------------|
| scoring_config per componenta | Admin Dashboard > LLM Components > Parameters | DA |
| stage_assignments per componenta | Admin Dashboard > LLM Components > Stage Assignments | DA |
| prompts per componenta | Admin Dashboard > LLM Components > Prompts | DA |
| input_profiles | Admin Dashboard > LLM Components > Verdict > Input Profiles | DA |
| vision_models | Admin Dashboard > LLM Components > AI Tampered > Vision Models | Pentru imagine/video |
**SECVENTA**: Adauga date in PG (admin dashboard) -> POST /api/sync-redis -> Verificare Redis keys
---
## Anexa E: Servicii externe (GPU)
### Masina GPU: 10.11.10.17
| Serviciu | Port | Scop | Folosit de |
|----------|------|------|------------|
| M17-Whisper | 54300 | Transcriere audio primara | agent-v3 transcription.ts |
| M17 Web API | 51100 | Cautare web pt verificare claims | agent-v3 claims executor |
| Qwen Vision Local | 14011 | Analiza imagine locala (llamacpp) | agent-v3 vision.ts |
### API-uri cloud
| Provider | Scop | Fallback chain |
|----------|------|----------------|
| OpenRouter | Modele LLM principale (Gemini, GPT-4o, Claude) | Primary |
| OpenAI | Whisper + LLM fallback | Fallback 1 |
| Groq | Whisper + LLM fallback (rapid) | Fallback 2 |
| Anthropic | LLM fallback (optional) | Fallback 3 |
### Domain Check API
| Serviciu | Adresa | Scop |
|----------|--------|------|
| Domain Check | <domain-check-host>:11000 | WHOIS, DNS, SSL, blacklist |
---
## Anexa F: Porturi utilizate
### Porturi externe (accesibile din afara)
| Port | Serviciu | Protocol |
|------|----------|----------|
| 443 | Kong Gateway (SSL) | HTTPS |
| 3000 | Admin Dashboard (SSL) | HTTPS |
| 9000 | MinIO API | HTTP |
### Porturi interne (doar localhost sau Docker network)
| Port | Serviciu | Acces |
|------|----------|-------|
| 24803 | agent-v3 | 127.0.0.1 |
| 3005 | didiFramework | Docker network |
| 6379 | Redis | Docker network |
| 5672 | RabbitMQ AMQP | 127.0.0.1 |
| 15672 | RabbitMQ Management | 127.0.0.1 |
| 9001 | MinIO Console | 127.0.0.1 |
| 8080 | Keycloak | 127.0.0.1 |
| 5050 | pgAdmin | 127.0.0.1 |
### Porturi GPU (retea interna)
| Port | Serviciu | Host |
|------|----------|------|
| 54300 | M17-Whisper | 10.11.10.17 |
| 51100 | M17 Web Search | 10.11.10.17 |
| 14011 | Qwen Vision | 10.11.10.17 |
---
## Script complet one-shot (TLDR)
```bash
#!/bin/bash
set -e
BACKEND=/home/admin365/didi_mono/backend
echo "=== ETAPA 1: Docker network ==="
docker network create didi-network 2>/dev/null || true
echo "=== ETAPA 2: PostgreSQL (presupunem ca exista + schemas create) ==="
echo "MANUAL: Ruleaza SQL din sectiunile 2.2 - 2.7 pe clusterul 10.11.50.167:5000"
echo "=== ETAPA 3: Data Layer ==="
docker volume create didi-staging-postgres-data 2>/dev/null || true
docker volume create didi-staging-minio-data 2>/dev/null || true
docker volume create didi-staging-pgadmin-data 2>/dev/null || true
cd $BACKEND/production && docker compose up -d didi-cache
cd $BACKEND/services/data-layer && docker compose up -d staging-dataLayer-rabbitmq staging-dataLayer-minio staging-dataLayer-pgadmin staging-dataLayer-redis-commander
echo "Asteptare servicii data layer..."
sleep 15
echo "=== ETAPA 4: Keycloak ==="
cd $BACKEND/production && docker compose up -d keycloak
echo "Asteptare Keycloak (60s)..." && sleep 60
echo "=== ETAPA 5: Kong ==="
cd $BACKEND/services/gateway-auth-layer/didiKong && docker build -t didi-kong:latest .
cd $BACKEND/production && docker compose up -d kong
sleep 15
echo "=== ETAPA 6: didiFramework ==="
cd $BACKEND/services/orchestration-layer/didiFramework && docker build -t didi-framework:latest . && docker compose up -d
sleep 10
echo "=== ETAPA 7: Sync Redis ==="
echo "MANUAL: Populeaza bos_parammgmt cu date, apoi:"
echo "curl -X POST http://localhost:3005/api/sync-redis"
echo "=== ETAPA 8: agent-v3 ==="
cd $BACKEND/services/orchestration-layer/agent-v3 && docker compose up -d --build
sleep 15
echo "=== ETAPA 9: Admin Dashboard ==="
cd $BACKEND/admin-dashboard && docker build -t didi-admin:latest .
cd $BACKEND/services/data-layer && docker compose up -d didi-admin
echo "=== DONE ==="
echo "Platforma DIDI ar trebui sa fie operationala."
echo "Verifica: https://localhost:3000/admin/"
```