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

54 KiB

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
  2. Arhitectura serviciilor
  3. Ordinea de deploy (graf dependente)
  4. ETAPA 0: Pregatire masina
  5. ETAPA 1: Docker network
  6. ETAPA 2: PostgreSQL cluster extern
  7. ETAPA 3: Data Layer (Redis + RabbitMQ + MinIO + pgAdmin)
  8. ETAPA 4: Keycloak (autentificare)
  9. ETAPA 5: Kong (API gateway)
  10. ETAPA 6: didiFramework (CRUD parametri)
  11. ETAPA 7: Sync Redis (populare config)
  12. ETAPA 8: agent-v3 + workeri
  13. ETAPA 9: Admin Dashboard
  14. ETAPA 10: Verificare finala
  15. Anexa A: Toate variabilele de mediu
  16. Anexa B: Chei Redis complete
  17. Anexa C: Schema PostgreSQL completa
  18. Anexa D: Date seed necesare
  19. Anexa E: Servicii externe (GPU, API keys)
  20. Anexa F: Porturi utilizate

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 :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

#!/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

# === 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:

psql -h 10.11.50.167 -p 5000 -U postgres
-- 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

psql -h 10.11.50.167 -p 5000 -U bos_interface -d DIDI
-- 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)

-- === 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)

-- === 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)

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)

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

-- 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

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

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

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

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

# === 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.

# === 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

# === 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

# === 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

#!/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 :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)

#!/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/"