stratumiops/docs/es/ia/ia-stratumiops-projects-technical-specs.md
Jesús Pérez 1680d80a3d
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
chore: Init repo, add docs
2026-01-22 22:15:19 +00:00

42 KiB

Portfolio IA: Especificaciones Técnicas para Desarrolladores

Arquitectura del Ecosistema

┌─────────────────────────────────────────────────────────────────────────────┐
│                           CAPA DE PRESENTACIÓN                              │
├─────────────────────────────────────────────────────────────────────────────┤
│  Leptos WASM (Vapora UI)  │  Ratatui TUI  │  Axum REST  │  CLI (clap)       │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           CAPA DE ORQUESTACIÓN                              │
├─────────────────────────────────────────────────────────────────────────────┤
│  Vapora Coordinator  │  TypeDialog Backends  │  Provisioning Orchestrator   │
│  (NATS JetStream)    │  (BackendFactory)     │  (Rust/Nushell hybrid)       │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           CAPA DE CONOCIMIENTO                              │
├─────────────────────────────────────────────────────────────────────────────┤
│  Kogral Knowledge Graph  │  Vapora Learning Profiles  │  Provisioning RAG   │
│  (6 node types)          │  (expertise + recency)     │  (1200+ docs)       │
└─────────────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           CAPA DE PERSISTENCIA                              │
├─────────────────────────────────────────────────────────────────────────────┤
│  SurrealDB (multi-tenant scopes)  │  Filesystem (git-native markdown)       │
│  NATS JetStream (mensajería)      │  Redis (vector stores opcionales)       │
│  etcd (SecretumVault HA)          │  PostgreSQL (vault enterprise)          │
└─────────────────────────────────────────────────────────────────────────────┘

1. Vapora: Especificaciones

Workspace Structure

crates/
├── vapora-shared/         # Core: models, errors, types
├── vapora-backend/        # Axum REST API (40+ endpoints)
├── vapora-agents/         # Agent orchestration + learning
├── vapora-llm-router/     # Multi-provider routing + budget
├── vapora-swarm/          # Swarm coordination + metrics
├── vapora-knowledge-graph/# Temporal KG + learning curves
├── vapora-frontend/       # Leptos WASM UI
├── vapora-mcp-server/     # MCP protocol gateway
├── vapora-tracking/       # Task/project storage
├── vapora-telemetry/      # OpenTelemetry integration
├── vapora-analytics/      # Event pipeline
├── vapora-worktree/       # Git worktree management
└── vapora-doc-lifecycle/  # Documentation management

Core Types

// vapora-shared/src/models.rs
pub struct Agent {
    pub id: String,
    pub role: AgentRole,           // 12 roles disponibles
    pub status: AgentStatus,       // Ready | Busy | Offline
    pub provider: LLMProvider,     // Claude | OpenAI | Gemini | Ollama
    pub last_heartbeat: DateTime<Utc>,
}

pub enum AgentRole {
    Architect, Developer, CodeReviewer, Tester,
    Documenter, Marketer, Presenter, DevOps,
    Monitor, Security, ProjectManager, DecisionMaker,
}

// vapora-agents/src/learning_profile.rs
pub struct ExpertiseProfile {
    pub task_type: String,
    pub success_rate: f64,
    pub avg_duration: Duration,
    pub execution_count: u32,
    pub recent_weight: f64,        // 3x for last 7 days
    pub confidence: f64,           // prevents overfitting on small samples
}

// Scoring formula
fn calculate_score(load: f64, expertise: f64, confidence: f64) -> f64 {
    0.3 * load + 0.5 * expertise + 0.2 * confidence
}

LLM Router Configuration

// vapora-llm-router/src/config.rs
pub struct RoutingRule {
    pub pattern: String,           // regex para task type
    pub provider: LLMProvider,
    pub model: String,
    pub fallback_chain: Vec<LLMProvider>,
}

pub struct BudgetConfig {
    pub role: AgentRole,
    pub monthly_limit_cents: u32,
    pub weekly_limit_cents: Option<u32>,
    pub enforcement: BudgetEnforcement,  // Normal | NearThreshold | Exceeded
}

// Cost tracking per request
pub struct CostRecord {
    pub provider: LLMProvider,
    pub model: String,
    pub input_tokens: u32,
    pub output_tokens: u32,
    pub cost_cents: f64,
    pub task_type: String,
    pub timestamp: DateTime<Utc>,
}

API Endpoints (Axum)

// vapora-backend/src/api/mod.rs
Router::new()
    // Projects
    .route("/projects", get(list_projects).post(create_project))
    .route("/projects/:id", get(get_project).put(update_project).delete(delete_project))

    // Tasks
    .route("/tasks", get(list_tasks).post(create_task))
    .route("/tasks/:id/assign", post(assign_to_agent))

    // Agents
    .route("/agents", get(list_agents))
    .route("/agents/:id/health", get(agent_health))
    .route("/agents/:role/expertise", get(role_expertise))

    // LLM Router
    .route("/llm/route", post(route_request))
    .route("/llm/budget/:role", get(get_budget).put(set_budget))
    .route("/llm/costs", get(cost_report))

    // Swarm
    .route("/swarm/assign", post(assign_task))
    .route("/swarm/status", get(swarm_status))

    // Metrics
    .route("/metrics", get(prometheus_metrics))

NATS Message Types

// vapora-agents/src/messages.rs
#[derive(Serialize, Deserialize)]
pub enum AgentMessage {
    TaskAssignment {
        task_id: String,
        agent_id: String,
        task_type: String,
        payload: serde_json::Value,
    },
    TaskResult {
        task_id: String,
        agent_id: String,
        status: TaskStatus,
        output: Option<String>,
        duration_ms: u64,
        tokens_used: u32,
    },
    Heartbeat {
        agent_id: String,
        status: AgentStatus,
        current_load: f64,
    },
}

// Subjects
const TASK_ASSIGNMENT: &str = "vapora.tasks.assign";
const TASK_RESULTS: &str = "vapora.tasks.results";
const AGENT_HEARTBEAT: &str = "vapora.agents.heartbeat";

2. Kogral: Especificaciones

Workspace Structure

crates/
├── kogral-core/           # Core library (models, storage, query)
├── kogral-cli/            # CLI (13 commands)
└── kogral-mcp/            # MCP server for Claude Code

Node Types

// kogral-core/src/models.rs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NodeType {
    Note,                  // General notes
    Decision,              // ADRs (Architectural Decision Records)
    Guideline,             // Team/org standards
    Pattern,               // Reusable solutions
    Journal,               // Daily development log
    Execution,             // Agent execution records
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RelationType {
    RelatesTo,
    DependsOn,
    Implements,
    Extends,
    Supersedes,
    Explains,
}

pub struct Node {
    pub id: String,
    pub node_type: NodeType,
    pub title: String,
    pub content: String,              // Markdown body
    pub metadata: HashMap<String, String>,
    pub tags: Vec<String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

pub struct Edge {
    pub source: String,               // Node ID
    pub target: String,               // Node ID
    pub relation: RelationType,
    pub weight: f64,                  // Relationship strength
}

Storage Backends

// kogral-core/src/storage/mod.rs
#[async_trait]
pub trait Storage: Send + Sync {
    async fn create_node(&self, node: &Node) -> Result<String>;
    async fn get_node(&self, id: &str) -> Result<Option<Node>>;
    async fn update_node(&self, node: &Node) -> Result<()>;
    async fn delete_node(&self, id: &str) -> Result<()>;
    async fn list_nodes(&self, filter: NodeFilter) -> Result<Vec<Node>>;

    async fn create_edge(&self, edge: &Edge) -> Result<()>;
    async fn get_edges(&self, node_id: &str) -> Result<Vec<Edge>>;
    async fn delete_edge(&self, source: &str, target: &str) -> Result<()>;

    async fn search(&self, query: &str, limit: usize) -> Result<Vec<Node>>;
    async fn semantic_search(&self, embedding: &[f32], limit: usize) -> Result<Vec<Node>>;
}

// Implementations
pub struct FilesystemStorage { /* .kogral/ directory */ }
pub struct SurrealDbStorage { /* SurrealDB connection */ }
pub struct MemoryStorage { /* DashMap for testing */ }

Embedding Configuration

// kogral-core/src/embeddings.rs
pub enum EmbeddingProvider {
    FastEmbed {
        model: String,  // "BAAI/bge-small-en-v1.5"
        dimensions: usize,  // 384
    },
    OpenAI {
        model: String,  // "text-embedding-3-small"
        api_key: String,
    },
    Ollama {
        model: String,
        url: String,
    },
}

#[async_trait]
pub trait Embedder: Send + Sync {
    async fn embed(&self, text: &str) -> Result<Vec<f32>>;
    async fn embed_batch(&self, texts: &[String]) -> Result<Vec<Vec<f32>>>;
    fn dimensions(&self) -> usize;
}

MCP Server Tools

// kogral-mcp/src/tools.rs
pub const MCP_TOOLS: &[Tool] = &[
    Tool {
        name: "search",
        description: "Search knowledge graph by text or semantic similarity",
        parameters: json!({
            "query": { "type": "string" },
            "node_type": { "type": "string", "optional": true },
            "limit": { "type": "integer", "default": 10 }
        }),
    },
    Tool {
        name: "add_note",
        description: "Add a new note to the knowledge graph",
        parameters: json!({
            "title": { "type": "string" },
            "content": { "type": "string" },
            "tags": { "type": "array", "items": { "type": "string" } }
        }),
    },
    Tool {
        name: "add_decision",
        description: "Record an architectural decision (ADR)",
        parameters: json!({
            "title": { "type": "string" },
            "context": { "type": "string" },
            "decision": { "type": "string" },
            "consequences": { "type": "string" }
        }),
    },
    Tool {
        name: "link",
        description: "Create relationship between nodes",
        parameters: json!({
            "source_id": { "type": "string" },
            "target_id": { "type": "string" },
            "relation": { "type": "string", "enum": ["relates_to", "depends_on", "implements", "extends", "supersedes", "explains"] }
        }),
    },
    Tool {
        name: "get_guidelines",
        description: "Get applicable guidelines for a topic",
        parameters: json!({
            "topic": { "type": "string" },
            "include_shared": { "type": "boolean", "default": true }
        }),
    },
    Tool {
        name: "list_graphs",
        description: "List available knowledge graphs",
        parameters: json!({}),
    },
    Tool {
        name: "export",
        description: "Export knowledge graph to format",
        parameters: json!({
            "format": { "type": "string", "enum": ["markdown", "json", "yaml"] },
            "filter": { "type": "object", "optional": true }
        }),
    },
];

CLI Commands

# kogral-cli commands
kogral init                    # Initialize .kogral/ directory
kogral add note <title>        # Add note interactively
kogral add decision <title>    # Add ADR with guided prompts
kogral search <query>          # Text search
kogral search --semantic <q>   # Semantic search
kogral link <src> <dst> <rel>  # Create relationship
kogral list [--type <type>]    # List nodes
kogral show <id>               # Display node details
kogral delete <id>             # Remove node
kogral graph                   # Visualize graph (DOT format)
kogral sync                    # Sync filesystem ↔ SurrealDB
kogral serve                   # Start MCP server
kogral import <path>           # Import from Logseq/markdown
kogral export <format>         # Export to markdown/json
kogral config                  # Show/edit configuration

3. TypeDialog: Especificaciones

Workspace Structure

crates/
├── typedialog-core/           # Core (forms, backends, validation)
├── typedialog/                # CLI binary
├── typedialog-tui/            # TUI binary (ratatui)
├── typedialog-web/            # Web binary (axum)
├── typedialog-ai/             # AI backend (RAG, embeddings)
├── typedialog-agent/
│   ├── typedialog-ag-core/    # Agent runtime
│   └── typedialog-ag/         # Agent CLI
└── typedialog-prov-gen/       # IaC generation

Form Definition (TOML)

# employee_onboarding.toml
[form]
id = "employee_onboarding"
version = "1.0.0"
title = "Employee Onboarding"
description = "New employee registration form"

[[sections]]
id = "personal"
title = "Personal Information"

[[sections.fields]]
id = "full_name"
type = "text"
label = "Full Name"
required = true
validation.min_length = 2
validation.max_length = 100

[[sections.fields]]
id = "department"
type = "select"
label = "Department"
required = true
options = [
    { value = "engineering", label = "Engineering" },
    { value = "product", label = "Product" },
    { value = "design", label = "Design" },
]

[[sections.fields]]
id = "skills"
type = "multi-select"
label = "Skills"
display_mode = "grid"
options = [
    { value = "rust", label = "Rust" },
    { value = "typescript", label = "TypeScript" },
    { value = "python", label = "Python" },
]

[[sections.fields]]
id = "start_date"
type = "date"
label = "Start Date"
default = "today"

[output]
format = "json"
validation = "nickel://schemas/employee.ncl"

Backend Trait

// typedialog-core/src/backend.rs
#[async_trait]
pub trait Backend: Send + Sync {
    fn name(&self) -> &str;

    async fn execute(&self, form: &Form) -> Result<FormResponse>;

    async fn render_field(&self, field: &Field, value: Option<&Value>) -> Result<Value>;

    fn supports_streaming(&self) -> bool { false }
}

pub struct BackendFactory;

impl BackendFactory {
    pub fn create(backend_type: BackendType) -> Box<dyn Backend> {
        match backend_type {
            BackendType::Cli => Box::new(CliBackend::new()),
            BackendType::Tui => Box::new(TuiBackend::new()),
            BackendType::Web => Box::new(WebBackend::new()),
            BackendType::Ai => Box::new(AiBackend::new()),
            BackendType::Agent => Box::new(AgentBackend::new()),
            BackendType::ProvGen => Box::new(ProvGenBackend::new()),
        }
    }
}

Agent MDX Format

---
name: code_reviewer
version: "1.0"
provider: claude
model: claude-sonnet-4-20250514
temperature: 0.3
max_tokens: 4096
---

# Code Review Agent

## System Prompt

You are an expert code reviewer. Review the following code for:

- Security vulnerabilities
- Performance issues
- Code style and best practices
- Potential bugs

## Template Variables

- `{{language}}`: Programming language
- `{{code}}`: Code to review
- `{{guidelines}}`: Project-specific guidelines

## User Prompt

Review this {{language}} code:

` ` `{{language}}
{{code}}
` ` `

Project guidelines:

{{guidelines}}

Provide a structured review with severity levels (critical, warning, info).

## Output Validation

format: json
schema: |
  {
    "issues": [{
      "severity": "critical | warning | info",
      "line": number,
      "message": string,
      "suggestion": string
    }],
    "summary": string
  }

Nickel Contract Integration

// typedialog-core/src/nickel.rs
pub struct NickelValidator {
    runtime: nickel_lang_core::eval::Runtime,
}

impl NickelValidator {
    pub fn validate(&self, data: &Value, contract_path: &str) -> Result<ValidationResult> {
        let contract = self.runtime.load(contract_path)?;
        let result = self.runtime.eval_with_contract(data, contract)?;
        Ok(result)
    }

    pub fn extract_schema(&self, contract_path: &str) -> Result<FormSchema> {
        // Parse Nickel contract and generate form schema
        let contract = self.runtime.load(contract_path)?;
        FormSchema::from_nickel_contract(&contract)
    }
}

Prov-Gen Output

// typedialog-prov-gen/src/generator.rs
pub enum CloudProvider {
    Aws,
    Gcp,
    Azure,
    Hetzner,
    UpCloud,
    Lxd,
}

pub struct InfrastructureConfig {
    pub provider: CloudProvider,
    pub region: String,
    pub resources: Vec<Resource>,
    pub networking: NetworkConfig,
    pub security: SecurityConfig,
}

pub struct Generator {
    templates: tera::Tera,
    validators: Vec<Box<dyn Validator>>,  // 7-layer validation
}

impl Generator {
    pub async fn generate(&self, config: &InfrastructureConfig) -> Result<GeneratedIaC> {
        // 1. Validate input config
        self.validate_config(config)?;

        // 2. Load provider-specific templates
        let template = self.templates.get_template(&format!("{}.ncl.tera", config.provider))?;

        // 3. Render Nickel configuration
        let nickel_code = template.render(&config)?;

        // 4. Validate generated Nickel
        self.validate_nickel(&nickel_code)?;

        Ok(GeneratedIaC {
            provider: config.provider,
            code: nickel_code,
            files: self.split_to_files(&nickel_code)?,
        })
    }
}

4. Provisioning: Especificaciones

Directory Structure

provisioning/
├── core/
│   ├── cli/               # Main CLI (211 lines)
│   ├── nulib/             # Nushell libraries (476+ accessors)
│   └── scripts/           # Utility scripts
├── extensions/
│   ├── providers/         # AWS, UpCloud, Local
│   ├── taskservs/         # 50+ infrastructure services
│   ├── clusters/          # Deployment templates
│   └── workflows/         # Automation workflows
├── platform/
│   ├── orchestrator/      # Workflow execution (Rust)
│   ├── control-center/    # Backend (Axum + RBAC)
│   ├── control-center-ui/ # Web dashboard (Leptos)
│   ├── installer/         # Multi-mode installer
│   ├── mcp-server/        # MCP server (Rust)
│   ├── ai-service/        # AI operations
│   ├── rag/               # RAG system
│   ├── vault-service/     # Secrets management
│   └── detector/          # Anomaly detection
└── schemas/               # Nickel IaC schemas

Nickel IaC Schema

# schemas/server.ncl
let Server = {
  name | String,
  provider | [ |  'aws, 'upcloud, 'local |],

  spec | {
    cpu | Number | default = 2,
    memory_gb | Number | default = 4,
    disk_gb | Number | default = 50,

    os | {
      family | [ |  'ubuntu, 'debian, 'rocky |],
      version | String,
    },
  },

  networking | {
    vpc | String | optional,
    subnet | String | optional,
    public_ip | Bool | default = false,
    security_groups | Array String | default = [],
  },

  tags | { _ : String } | default = {},
}
in Server

Orchestrator API

// platform/orchestrator/src/lib.rs
pub struct Orchestrator {
    state: StateManager,
    executor: WorkflowExecutor,
    scheduler: Scheduler,
}

impl Orchestrator {
    pub async fn execute_workflow(&self, workflow: Workflow) -> Result<ExecutionResult> {
        // 1. Resolve dependencies (topological sort)
        let ordered_tasks = self.resolve_dependencies(&workflow)?;

        // 2. Create execution checkpoints
        let checkpoint = self.state.create_checkpoint(&workflow)?;

        // 3. Execute tasks with retry logic
        for task in ordered_tasks {
            match self.executor.run(&task).await {
                Ok(result) => {
                    self.state.record_success(&task, &result)?;
                }
                Err(e) => {
                    // Exponential backoff retry
                    if let Some(result) = self.retry_with_backoff(&task).await? {
                        self.state.record_success(&task, &result)?;
                    } else {
                        // Rollback to checkpoint
                        self.state.rollback(&checkpoint)?;
                        return Err(e);
                    }
                }
            }
        }

        Ok(ExecutionResult::from_state(&self.state))
    }
}

MCP Tools

// platform/mcp-server/src/tools.rs
pub const MCP_TOOLS: &[Tool] = &[
    Tool {
        name: "query_infrastructure",
        description: "Query infrastructure state using natural language",
        parameters: json!({
            "query": { "type": "string" },
            "provider": { "type": "string", "optional": true }
        }),
    },
    Tool {
        name: "generate_config",
        description: "Generate Nickel configuration from description",
        parameters: json!({
            "description": { "type": "string" },
            "provider": { "type": "string" },
            "resource_type": { "type": "string" }
        }),
    },
    Tool {
        name: "validate_config",
        description: "Validate Nickel configuration",
        parameters: json!({
            "config": { "type": "string" },
            "strict": { "type": "boolean", "default": true }
        }),
    },
    Tool {
        name: "estimate_cost",
        description: "Estimate monthly cost for configuration",
        parameters: json!({
            "config": { "type": "string" },
            "region": { "type": "string", "optional": true }
        }),
    },
    Tool {
        name: "check_compliance",
        description: "Check configuration against compliance rules",
        parameters: json!({
            "config": { "type": "string" },
            "framework": { "type": "string", "enum": ["soc2", "hipaa", "gdpr", "pci"] }
        }),
    },
    Tool {
        name: "plan_migration",
        description: "Generate migration plan between configurations",
        parameters: json!({
            "current": { "type": "string" },
            "target": { "type": "string" }
        }),
    },
    Tool {
        name: "execute_workflow",
        description: "Execute provisioning workflow",
        parameters: json!({
            "workflow_id": { "type": "string" },
            "dry_run": { "type": "boolean", "default": true }
        }),
    },
];

RAG Configuration

// platform/rag/src/config.rs
pub struct RagConfig {
    pub embedding_model: String,       // "text-embedding-3-small"
    pub embedding_dimensions: usize,   // 1536
    pub chunk_size: usize,             // 512 tokens
    pub chunk_overlap: usize,          // 50 tokens
    pub top_k: usize,                  // 5 results
    pub min_similarity: f32,           // 0.7
    pub reranker: Option<RerankerConfig>,
}

pub struct RagService {
    embedder: Box<dyn Embedder>,
    vector_store: Box<dyn VectorStore>,
    keyword_index: tantivy::Index,
}

impl RagService {
    pub async fn query(&self, question: &str) -> Result<Vec<Document>> {
        // 1. Generate embedding for question
        let embedding = self.embedder.embed(question).await?;

        // 2. Vector similarity search
        let vector_results = self.vector_store.search(&embedding, self.config.top_k).await?;

        // 3. BM25 keyword search
        let keyword_results = self.keyword_search(question)?;

        // 4. Hybrid ranking (RRF)
        let merged = self.reciprocal_rank_fusion(vector_results, keyword_results);

        // 5. Optional reranking
        if let Some(reranker) = &self.reranker {
            return reranker.rerank(&merged, question).await;
        }

        Ok(merged)
    }
}

5. SecretumVault: Especificaciones

Arquitectura General

┌─────────────────────────────────────────────────────────────────┐
│  SecretumVault (~11K LOC, 50+ tests)                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │  CLI        │  │  REST API   │  │      Secrets Engines    │  │
│  │  (clap)     │  │  (Axum)     │  │  KV/Transit/PKI/DB      │  │
│  └──────┬──────┘  └──────┬──────┘  └────────────┬────────────┘  │
│         │                │                      │               │
│  ┌──────┴────────────────┴──────────────────────┴─────────────┐ │
│  │                    VaultCore                               │ │
│  │  Seal (Shamir) │ TokenManager │ Cedar ABAC │ Metrics       │ │
│  └────────────────────────────────────────────────────────────┘ │
│                          │                                      │
│  ┌───────────────────────┴───────────────────────────────────┐  │
│  │  Crypto Backends                                          │  │
│  │  OpenSSL │ OQS (PQC) │ AWS-LC │ RustCrypto                │  │
│  └───────────────────────────────────────────────────────────┘  │
│                          │                                      │
│  ┌───────────────────────┴───────────────────────────────────┐  │
│  │  Storage Backends                                         │  │
│  │  Filesystem │ etcd │ SurrealDB │ PostgreSQL               │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

Core Types

// src/core/vault.rs
pub struct VaultCore {
    pub engines: HashMap<String, Box<dyn Engine>>,
    pub storage: Arc<dyn StorageBackend>,
    pub crypto: Arc<dyn CryptoBackend>,
    pub seal: Arc<tokio::sync::Mutex<SealMechanism>>,
    pub token_manager: Arc<TokenManager>,
    pub metrics: Arc<Metrics>,
}

// src/crypto/mod.rs
#[async_trait]
pub trait CryptoBackend: Send + Sync {
    async fn generate_keypair(&self, algorithm: KeyAlgorithm) -> CryptoResult<KeyPair>;
    async fn sign(&self, key: &PrivateKey, data: &[u8]) -> CryptoResult<Vec<u8>>;
    async fn verify(&self, key: &PublicKey, data: &[u8], sig: &[u8]) -> CryptoResult<bool>;
    async fn encrypt(&self, plaintext: &[u8]) -> CryptoResult<Vec<u8>>;
    async fn decrypt(&self, ciphertext: &[u8]) -> CryptoResult<Vec<u8>>;

    // Post-Quantum (OQS backend)
    async fn kem_encapsulate(&self, public_key: &[u8]) -> CryptoResult<KemResult>;
    async fn kem_decapsulate(&self, ciphertext: &[u8]) -> CryptoResult<Vec<u8>>;
}

// src/storage/mod.rs
#[async_trait]
pub trait StorageBackend: Send + Sync {
    async fn store_secret(&self, path: &str, data: &EncryptedData) -> StorageResult<()>;
    async fn get_secret(&self, path: &str) -> StorageResult<EncryptedData>;
    async fn delete_secret(&self, path: &str) -> StorageResult<()>;
    async fn list_secrets(&self, prefix: &str) -> StorageResult<Vec<String>>;
}

Crypto Backends

// src/crypto/backends/
pub enum CryptoBackendType {
    OpenSSL,     // RSA, ECDSA, AES-256-GCM
    Oqs,         // ML-KEM-768, ML-DSA-65 (NIST FIPS 203/204)
    AwsLc,       // RSA, ECDSA (experimental PQC)
    RustCrypto,  // AES-GCM, ChaCha20-Poly1305 (testing)
}

// OQS Post-Quantum (production-ready)
pub struct OqsBackend {
    kem_algorithm: oqs::kem::Algorithm,   // MlKem768
    sig_algorithm: oqs::sig::Algorithm,   // MlDsa65
}

impl OqsBackend {
    pub async fn kem_keygen(&self) -> CryptoResult<KemKeyPair> {
        // ML-KEM-768: 1088 bytes ciphertext, 32 bytes shared secret
        let kem = oqs::kem::Kem::new(self.kem_algorithm)?;
        let (pk, sk) = kem.keypair()?;
        Ok(KemKeyPair { public_key: pk, secret_key: sk })
    }

    pub async fn sign(&self, sk: &[u8], message: &[u8]) -> CryptoResult<Vec<u8>> {
        // ML-DSA-65 signatures
        let sig = oqs::sig::Sig::new(self.sig_algorithm)?;
        let signature = sig.sign(message, sk)?;
        Ok(signature.into_vec())
    }
}

Secrets Engines

// src/engines/mod.rs
pub trait Engine: Send + Sync {
    fn name(&self) -> &str;
    fn engine_type(&self) -> &str;
    async fn read(&self, path: &str) -> Result<Option<Value>>;
    async fn write(&self, path: &str, data: &Value) -> Result<()>;
    async fn delete(&self, path: &str) -> Result<()>;
    async fn list(&self, prefix: &str) -> Result<Vec<String>>;
}

// Engines disponibles
pub struct KvEngine { /* Versioned secret storage */ }
pub struct TransitEngine { /* Encryption-as-a-service */ }
pub struct PkiEngine { /* X.509 certificates */ }
pub struct DatabaseEngine { /* Dynamic credentials */ }

Seal Mechanism (Shamir)

// src/core/seal.rs
pub struct SealMechanism {
    state: SealState,
    shares: Vec<SecretShare>,
    threshold: u8,
    total_shares: u8,
}

pub enum SealState {
    Sealed,
    Unsealing { collected: usize },
    Unsealed { master_key: Vec<u8> },
}

impl SealMechanism {
    pub fn init(&mut self, shares: u8, threshold: u8) -> Result<Vec<SecretShare>> {
        // Generate master key and split with Shamir
        let master_key = generate_random_bytes(32)?;
        let sharks = Sharks(threshold);
        let dealer = sharks.dealer(&master_key);
        let shares: Vec<_> = dealer.take(shares as usize).collect();
        self.state = SealState::Sealed;
        Ok(shares)
    }

    pub fn unseal(&mut self, share: SecretShare) -> Result<UnsealProgress> {
        // Collect shares until threshold met
        self.shares.push(share);
        if self.shares.len() >= self.threshold as usize {
            let sharks = Sharks(self.threshold);
            let master_key = sharks.recover(&self.shares)?;
            self.state = SealState::Unsealed { master_key };
            return Ok(UnsealProgress::Complete);
        }
        Ok(UnsealProgress::NeedMore { collected: self.shares.len() })
    }
}

Authorization (Cedar ABAC)

// src/auth/cedar.rs
pub struct CedarAuthorizer {
    engine: cedar_policy::Authorizer,
    policies: cedar_policy::PolicySet,
}

impl CedarAuthorizer {
    pub fn authorize(&self, request: &AuthzRequest) -> Result<Decision> {
        let principal = self.build_principal(&request.user)?;
        let action = self.build_action(&request.action)?;
        let resource = self.build_resource(&request.resource)?;

        let decision = self.engine.is_authorized(
            &principal,
            &action,
            &resource,
            &self.policies,
        )?;

        Ok(decision)
    }
}

API Endpoints

// src/api/routes.rs
Router::new()
    // System
    .route("/v1/sys/health", get(health_check))
    .route("/v1/sys/init", post(initialize_vault))
    .route("/v1/sys/seal", post(seal_vault))
    .route("/v1/sys/unseal", post(unseal_vault))
    .route("/v1/sys/mounts", get(list_mounts))

    // Secrets (dynamic routing by engine)
    .route("/v1/*path", get(read_secret)
                        .post(write_secret)
                        .delete(delete_secret))

    // Metrics
    .route("/metrics", get(prometheus_metrics))

Configuration (TOML)

# svault.toml
[vault]
crypto_backend = "oqs"  # openssl | oqs | aws-lc | rustcrypto

[server]
address = "0.0.0.0:8200"
tls_cert = "/path/to/cert.pem"
tls_key = "/path/to/key.pem"

[storage]
backend = "etcd"  # filesystem | etcd | surrealdb | postgresql

[storage.etcd]
endpoints = ["http://localhost:2379"]

[seal.shamir]
shares = 5
threshold = 3

[auth]
token_ttl = "24h"

CLI Commands

# Server
svault server --config svault.toml

# Operator
svault operator init --shares 5 --threshold 3
svault operator unseal --share <share>
svault operator seal
svault operator status

# Secrets
svault secret read secret/myapp
svault secret write secret/myapp key=value
svault secret delete secret/myapp
svault secret list secret/

Feature Flags

# Cargo.toml features
[features]
default = ["openssl", "filesystem", "server", "pqc"]

# Crypto backends
openssl = ["dep:openssl"]
aws-lc = ["dep:aws-lc-rs"]
pqc = ["dep:oqs"]
rustcrypto = ["dep:aes-gcm", "dep:chacha20poly1305"]

# Storage backends
filesystem = []
surrealdb-storage = ["dep:surrealdb"]
etcd-storage = ["dep:etcd-client"]
postgresql-storage = ["dep:sqlx"]

# Components
server = ["dep:axum", "dep:rustls"]
cli = ["dep:clap"]
cedar = ["dep:cedar-policy"]

6. Integración entre Proyectos

Diagrama de Dependencias

                    ┌───────────────────┐
                    │      Kogral       │
                    │ (Knowledge Graph) │
                    └─────────┬─────────┘
                              │
             MCP (guidelines, patterns, decisions)
                              │
    ┌─────────────────────────┼─────────────────────────┐
    │                         │                         │
    ▼                         ▼                         ▼
┌─────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   Vapora    │  │   TypeDialog    │  │  Provisioning   │
│(Orchestrate)│  │   (Forms/UI)    │  │     (IaC)       │
└──────┬──────┘  └────────┬────────┘  └────────┬────────┘
       │                  │                    │
       │    ┌─────────────┴─────────────┐      │
       │    │                           │      │
       │    ▼                           ▼      │
       │  ┌───────────────────────────────┐    │
       │  │       SecretumVault           │    │
       │  │    (Secrets + PQC Crypto)     │    │
       │  └───────────────────────────────┘    │
       │                  │                    │
       └──────────────────┼────────────────────┘
                          │
                ┌─────────┴─────────┐
                │     SurrealDB     │
                │ (Shared State)    │
                └───────────────────┘

Shared Dependencies (Cargo.toml)

# Dependencias comunes a todos los proyectos
[dependencies]
# Runtime
tokio = { version = "1.48", features = ["full"] }

# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# Database
surrealdb = "2.3"

# Web
axum = "0.8"

# LLM
rig-core = "0.15"

# Config
nickel-lang-core = "1.15"

# Logging
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }

# Error handling
anyhow = "1.0"
thiserror = "2.0"

SurrealDB Schema Compartido

-- Namespace compartido para cross-project state
DEFINE NAMESPACE portfolio;

-- Scope para cada proyecto
DEFINE DATABASE vapora;
DEFINE DATABASE kogral;
DEFINE DATABASE typedialog;
DEFINE DATABASE provisioning;
DEFINE DATABASE secretumvault;

-- Tabla compartida para execution records
DEFINE TABLE executions SCHEMAFULL;
DEFINE FIELD project ON executions TYPE string;
DEFINE FIELD task_type ON executions TYPE string;
DEFINE FIELD agent_id ON executions TYPE string;
DEFINE FIELD status ON executions TYPE string;
DEFINE FIELD duration_ms ON executions TYPE int;
DEFINE FIELD tokens_used ON executions TYPE int;
DEFINE FIELD cost_cents ON executions TYPE float;
DEFINE FIELD created_at ON executions TYPE datetime DEFAULT time::now();

-- Índices para queries cross-project
DEFINE INDEX idx_executions_project ON executions FIELDS project;
DEFINE INDEX idx_executions_agent ON executions FIELDS agent_id;

Ejemplo de Integración: Feature Development

// Flujo integrado de desarrollo de feature
async fn develop_feature(feature_spec: &str) -> Result<FeatureResult> {
    // 1. Kogral: Obtener contexto del proyecto
    let kogral_client = KogralMcpClient::connect().await?;
    let guidelines = kogral_client.call("get_guidelines", json!({
        "topic": feature_spec,
        "include_shared": true
    })).await?;

    let patterns = kogral_client.call("search", json!({
        "query": feature_spec,
        "node_type": "pattern",
        "limit": 5
    })).await?;

    // 2. TypeDialog: Capturar configuración adicional
    let typedialog = TypeDialog::new(BackendType::Cli);
    let config = typedialog.execute_form("feature_config.toml").await?;

    // 3. Vapora: Orquestar agentes
    let vapora_client = VaporaClient::new("http://localhost:8001");

    // Crear tarea con contexto
    let task = vapora_client.create_task(TaskRequest {
        title: format!("Implement: {}", feature_spec),
        context: json!({
            "guidelines": guidelines,
            "patterns": patterns,
            "config": config,
        }),
        task_type: "feature_implementation",
    }).await?;

    // Ejecutar pipeline
    let pipeline = vec![
        ("architect", "Design feature architecture"),
        ("developer", "Implement feature"),
        ("reviewer", "Review implementation"),
        ("tester", "Write and run tests"),
    ];

    for (role, description) in pipeline {
        vapora_client.assign_task(&task.id, role, description).await?;
        vapora_client.wait_for_completion(&task.id).await?;
    }

    // 4. Kogral: Registrar decisión
    kogral_client.call("add_decision", json!({
        "title": format!("Feature: {}", feature_spec),
        "context": &task.context,
        "decision": &task.result,
        "consequences": "Implementation completed"
    })).await?;

    // 5. Provisioning: Desplegar si es necesario
    if config.requires_infra {
        let prov_client = ProvisioningMcpClient::connect().await?;
        prov_client.call("execute_workflow", json!({
            "workflow_id": config.deployment_workflow,
            "dry_run": false
        })).await?;
    }

    Ok(FeatureResult {
        task_id: task.id,
        status: task.status,
    })
}

7. Métricas de Calidad

Proyecto Tests Cobertura Clippy Unsafe Doc Coverage
Vapora 218 ~70% 0 warnings 0 100% public
Kogral 56 ~80% 0 warnings 0 100% public
TypeDialog 3,818 ~85% 0 warnings 0 100% public
Provisioning 218 ~65% 0 warnings 0 100% public
SecretumVault 50+ ~75% 0 warnings 0 100% public

Comandos de Verificación

# Por proyecto
cargo clippy --all-targets --all-features -- -D warnings
cargo test --workspace
cargo doc --no-deps

# Coverage (requiere tarpaulin)
cargo tarpaulin --workspace --out Html

# Benchmarks
cargo bench --workspace

Documento generado: 2026-01-22 Tipo: info (especificaciones técnicas)