1785 lines
62 KiB
Markdown
1785 lines
62 KiB
Markdown
# Portfolio: Especificaciones Técnicas Completas
|
|
|
|
## Arquitectura del Ecosistema
|
|
|
|
```text
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
│ CAPA DE USUARIO │
|
|
├─────────────────────────────────────────────────────────────────────────────────┤
|
|
│ Leptos WASM │ Ratatui TUI │ CLI (clap) │ MCP Protocol │
|
|
│ (Vapora, Prov) │ (TypeDialog, │ (todos) │ (Kogral, Prov) │
|
|
│ │ Prov) │ │ │
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
│ CAPA DE API │
|
|
├─────────────────────────────────────────────────────────────────────────────────┤
|
|
│ Axum REST │ WebSocket │ JSON-RPC 2.0 │ NATS JetStream │
|
|
│ (40+ endpoints) │ (real-time) │ (MCP) │ (messaging) │
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌───────────────────────────────────────────────────────────────────────────────────────┐
|
|
│ CAPA DE DOMINIO │
|
|
├───────────────────────────────────────────────────────────────────────────────────────┤
|
|
│ Project Mgmt │ Knowledge Graph │ Form Engine │ IaC Engine │ Vault │
|
|
│ (Vapora) │ (Kogral) │ (TypeDialog) │ (Provisioning) │ (SecretumV.)│
|
|
│ │ │ │ │ │
|
|
│ Agent Coord │ Embeddings │ Agent Exec │ Orchestrator │ Seal/Unseal │
|
|
│ (Vapora) │ (Kogral) │ (TypeDialog) │ (Provisioning) │ (SecretumV.)│
|
|
│ │ │ │ │ │
|
|
│ LLM Router │ MCP Server │ Prov-gen │ Security Layer │ │
|
|
│ (Vapora) │ (Kogral) │ (TypeDialog) │ (Provisioning) │ │
|
|
└───────────────────────────────────────────────────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
│ CAPA DE PERSISTENCIA │
|
|
├─────────────────────────────────────────────────────────────────────────────────┤
|
|
│ SurrealDB │ Filesystem │ NATS JetStream │ etcd │ PG │
|
|
│ (multi-tenant │ (git-native │ (mensajería │ (SecretumVault │(Vault│
|
|
│ scopes) │ markdown) │ durable) │ HA) │ ent.)│
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## 1. Vapora: Especificaciones Completas
|
|
|
|
### Workspace (13 crates)
|
|
|
|
```text
|
|
crates/
|
|
├── vapora-shared/ # Core: models, errors, types
|
|
├── vapora-backend/ # Axum REST API (40+ endpoints, 79 tests)
|
|
├── vapora-agents/ # Agent orchestration + learning (67 tests)
|
|
├── vapora-llm-router/ # Multi-provider routing + budget (53 tests)
|
|
├── vapora-swarm/ # Swarm coordination + metrics (6 tests)
|
|
├── vapora-knowledge-graph/# Temporal KG + learning curves (13 tests)
|
|
├── vapora-frontend/ # Leptos WASM UI (Kanban)
|
|
├── 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
|
|
```
|
|
|
|
### Domain Models
|
|
|
|
```rust
|
|
// vapora-shared/src/models.rs
|
|
|
|
// ─── Project Management ───────────────────────────────────────
|
|
pub struct Project {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub description: Option<String>,
|
|
pub scope: String, // Multi-tenant scope
|
|
pub status: ProjectStatus,
|
|
pub created_at: DateTime<Utc>,
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
pub enum ProjectStatus {
|
|
Active,
|
|
Archived,
|
|
OnHold,
|
|
}
|
|
|
|
pub struct Task {
|
|
pub id: String,
|
|
pub project_id: String,
|
|
pub title: String,
|
|
pub description: Option<String>,
|
|
pub status: TaskStatus,
|
|
pub priority: TaskPriority,
|
|
pub assigned_agent: Option<String>,
|
|
pub tags: Vec<String>,
|
|
pub order: i32,
|
|
pub created_at: DateTime<Utc>,
|
|
}
|
|
|
|
pub enum TaskStatus {
|
|
Todo,
|
|
Doing,
|
|
Review,
|
|
Done,
|
|
}
|
|
|
|
pub enum TaskPriority {
|
|
Low,
|
|
Medium,
|
|
High,
|
|
Critical,
|
|
}
|
|
|
|
// ─── Agent System ─────────────────────────────────────────────
|
|
pub struct Agent {
|
|
pub id: String,
|
|
pub role: AgentRole,
|
|
pub status: AgentStatus,
|
|
pub provider: LLMProvider,
|
|
pub current_load: f64,
|
|
pub last_heartbeat: DateTime<Utc>,
|
|
}
|
|
|
|
pub enum AgentRole {
|
|
Architect,
|
|
Developer,
|
|
CodeReviewer,
|
|
Tester,
|
|
Documenter,
|
|
Marketer,
|
|
Presenter,
|
|
DevOps,
|
|
Monitor,
|
|
Security,
|
|
ProjectManager,
|
|
DecisionMaker,
|
|
}
|
|
|
|
pub enum AgentStatus {
|
|
Ready,
|
|
Busy,
|
|
Offline,
|
|
Maintenance,
|
|
}
|
|
|
|
// ─── Learning System ──────────────────────────────────────────
|
|
pub struct ExpertiseProfile {
|
|
pub agent_id: String,
|
|
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
|
|
pub last_updated: DateTime<Utc>,
|
|
}
|
|
|
|
// Scoring: 0.3*load + 0.5*expertise + 0.2*confidence
|
|
|
|
// ─── LLM Router ───────────────────────────────────────────────
|
|
pub enum LLMProvider {
|
|
Claude,
|
|
OpenAI,
|
|
Gemini,
|
|
Ollama,
|
|
}
|
|
|
|
pub struct RoutingRule {
|
|
pub pattern: String, // Regex for 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,
|
|
}
|
|
|
|
pub enum BudgetEnforcement {
|
|
Normal,
|
|
NearThreshold, // 80%+
|
|
Exceeded, // 100%+
|
|
}
|
|
|
|
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 agent_id: String,
|
|
pub timestamp: DateTime<Utc>,
|
|
}
|
|
```
|
|
|
|
### API Endpoints
|
|
|
|
```rust
|
|
// vapora-backend/src/api/mod.rs
|
|
|
|
// ─── Projects ─────────────────────────────────────────────────
|
|
GET /projects // List projects (filtered by scope)
|
|
POST /projects // Create project
|
|
GET /projects/:id // Get project details
|
|
PUT /projects/:id // Update project
|
|
DELETE /projects/:id // Archive project
|
|
|
|
// ─── Tasks ────────────────────────────────────────────────────
|
|
GET /projects/:id/tasks // List tasks for project
|
|
POST /tasks // Create task
|
|
GET /tasks/:id // Get task details
|
|
PUT /tasks/:id // Update task
|
|
DELETE /tasks/:id // Delete task
|
|
POST /tasks/:id/assign // Assign to agent
|
|
PUT /tasks/:id/status // Update status (Kanban)
|
|
PUT /tasks/:id/order // Reorder task
|
|
|
|
// ─── Agents ───────────────────────────────────────────────────
|
|
GET /agents // List all agents
|
|
GET /agents/:id // Get agent details
|
|
GET /agents/:id/health // Health check
|
|
GET /agents/:role/expertise // Get expertise for role
|
|
POST /agents/register // Register new agent
|
|
DELETE /agents/:id // Unregister agent
|
|
|
|
// ─── LLM Router ───────────────────────────────────────────────
|
|
POST /llm/route // Route request to provider
|
|
GET /llm/providers // List available providers
|
|
GET /llm/budget/:role // Get budget status
|
|
PUT /llm/budget/:role // Set budget limits
|
|
GET /llm/costs // Cost report
|
|
GET /llm/costs/:role // Cost by role
|
|
GET /llm/costs/:provider // Cost by provider
|
|
|
|
// ─── Swarm ────────────────────────────────────────────────────
|
|
POST /swarm/assign // Assign task to swarm
|
|
GET /swarm/status // Swarm status
|
|
GET /swarm/agents // List swarm agents
|
|
POST /swarm/balance // Rebalance load
|
|
|
|
// ─── Pipelines ────────────────────────────────────────────────
|
|
POST /pipelines // Create pipeline
|
|
GET /pipelines/:id // Get pipeline status
|
|
POST /pipelines/:id/approve // Approve gate
|
|
POST /pipelines/:id/cancel // Cancel pipeline
|
|
|
|
// ─── Knowledge Graph ──────────────────────────────────────────
|
|
POST /knowledge/query // Query knowledge graph
|
|
GET /knowledge/similar/:task_id // Find similar past tasks
|
|
GET /knowledge/learning/:agent // Get learning curve
|
|
|
|
// ─── Observability ────────────────────────────────────────────
|
|
GET /metrics // Prometheus metrics
|
|
GET /health // Health check
|
|
GET /health/ready // Readiness probe
|
|
GET /health/live // Liveness probe
|
|
```
|
|
|
|
### NATS Subjects
|
|
|
|
```rust
|
|
// vapora-agents/src/messages.rs
|
|
|
|
// ─── Task Assignment ──────────────────────────────────────────
|
|
const TASK_ASSIGN: &str = "vapora.tasks.assign";
|
|
// Payload: TaskAssignment { task_id, agent_id, task_type, payload }
|
|
|
|
const TASK_RESULT: &str = "vapora.tasks.results";
|
|
// Payload: TaskResult { task_id, agent_id, status, output, duration_ms, tokens }
|
|
|
|
// ─── Agent Coordination ───────────────────────────────────────
|
|
const AGENT_HEARTBEAT: &str = "vapora.agents.heartbeat";
|
|
// Payload: Heartbeat { agent_id, status, current_load }
|
|
|
|
const AGENT_REGISTER: &str = "vapora.agents.register";
|
|
// Payload: AgentRegistration { agent_id, role, capabilities }
|
|
|
|
// ─── Pipeline Events ──────────────────────────────────────────
|
|
const PIPELINE_STAGE: &str = "vapora.pipelines.stage";
|
|
// Payload: StageEvent { pipeline_id, stage, status }
|
|
|
|
const PIPELINE_APPROVAL: &str = "vapora.pipelines.approval";
|
|
// Payload: ApprovalRequest { pipeline_id, stage, requester }
|
|
```
|
|
|
|
### Frontend Components (Leptos)
|
|
|
|
```rust
|
|
// vapora-frontend/src/components/
|
|
|
|
// ─── Kanban Board ─────────────────────────────────────────────
|
|
#[component]
|
|
pub fn KanbanBoard(project_id: String) -> impl IntoView {
|
|
// Columns: Todo, Doing, Review, Done
|
|
// Drag-and-drop with optimistic updates
|
|
// WebSocket subscription for real-time sync
|
|
}
|
|
|
|
#[component]
|
|
pub fn KanbanColumn(status: TaskStatus, tasks: Vec<Task>) -> impl IntoView {
|
|
// Droppable zone
|
|
// Task cards with priority indicators
|
|
}
|
|
|
|
#[component]
|
|
pub fn TaskCard(task: Task) -> impl IntoView {
|
|
// Draggable card
|
|
// Tags, priority, assignee display
|
|
// Click to open details
|
|
}
|
|
|
|
// ─── Project Management ───────────────────────────────────────
|
|
#[component]
|
|
pub fn ProjectList() -> impl IntoView {
|
|
// Grid/list view toggle
|
|
// Filter by status
|
|
// Create project modal
|
|
}
|
|
|
|
#[component]
|
|
pub fn ProjectDetail(project_id: String) -> impl IntoView {
|
|
// Project info
|
|
// Kanban board
|
|
// Agent assignments
|
|
// Pipeline status
|
|
}
|
|
|
|
// ─── Agent Dashboard ──────────────────────────────────────────
|
|
#[component]
|
|
pub fn AgentOverview() -> impl IntoView {
|
|
// Agent status grid
|
|
// Load indicators
|
|
// Expertise heatmap
|
|
}
|
|
|
|
#[component]
|
|
pub fn CostDashboard() -> impl IntoView {
|
|
// Budget usage by role
|
|
// Cost trends charts
|
|
// Provider breakdown
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Kogral: Especificaciones Completas
|
|
|
|
### Workspace (3 crates)
|
|
|
|
```text
|
|
crates/
|
|
├── kogral-core/ # Core library (48 tests)
|
|
│ ├── models/ # Node, Edge, Graph types
|
|
│ ├── storage/ # Multi-backend storage
|
|
│ ├── parser/ # Markdown + YAML parser
|
|
│ ├── block_parser/ # Logseq block support
|
|
│ ├── query/ # Text + semantic search
|
|
│ ├── embeddings/ # fastembed + rig-core
|
|
│ ├── export/ # Tera templates
|
|
│ ├── sync/ # Filesystem ↔ SurrealDB
|
|
│ ├── config/ # Nickel config loader
|
|
│ └── inheritance/ # Guideline inheritance
|
|
├── kogral-cli/ # CLI (13 commands)
|
|
└── kogral-mcp/ # MCP server (7 tools)
|
|
```
|
|
|
|
### Domain Models
|
|
|
|
```rust
|
|
// kogral-core/src/models.rs
|
|
|
|
// ─── Node Types ───────────────────────────────────────────────
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum NodeType {
|
|
Note, // General notes
|
|
Decision, // ADRs
|
|
Guideline, // Standards
|
|
Pattern, // Reusable solutions
|
|
Journal, // Daily logs
|
|
Execution, // Agent records
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Node {
|
|
pub id: String,
|
|
pub node_type: NodeType,
|
|
pub title: String,
|
|
pub content: String, // Markdown body
|
|
pub metadata: HashMap<String, Value>,
|
|
pub tags: Vec<String>,
|
|
pub graph_id: String, // Which graph this belongs to
|
|
pub created_at: DateTime<Utc>,
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
// ─── Relationships ────────────────────────────────────────────
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum RelationType {
|
|
RelatesTo,
|
|
DependsOn,
|
|
Implements,
|
|
Extends,
|
|
Supersedes,
|
|
Explains,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Edge {
|
|
pub source: String,
|
|
pub target: String,
|
|
pub relation: RelationType,
|
|
pub weight: f64,
|
|
pub metadata: HashMap<String, Value>,
|
|
}
|
|
|
|
// ─── Graph ────────────────────────────────────────────────────
|
|
#[derive(Debug, Clone)]
|
|
pub struct Graph {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub graph_type: GraphType,
|
|
pub nodes: HashMap<String, Node>,
|
|
pub edges: Vec<Edge>,
|
|
}
|
|
|
|
pub enum GraphType {
|
|
Project, // Local, in .kogral/
|
|
Shared, // Organization-wide, in SurrealDB
|
|
}
|
|
|
|
// ─── ADR Structure ────────────────────────────────────────────
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct DecisionRecord {
|
|
pub title: String,
|
|
pub status: DecisionStatus,
|
|
pub context: String,
|
|
pub decision: String,
|
|
pub consequences: String,
|
|
pub alternatives: Vec<Alternative>,
|
|
pub related_decisions: Vec<String>,
|
|
}
|
|
|
|
pub enum DecisionStatus {
|
|
Proposed,
|
|
Accepted,
|
|
Deprecated,
|
|
Superseded,
|
|
}
|
|
|
|
// ─── Logseq Blocks ────────────────────────────────────────────
|
|
#[derive(Debug, Clone)]
|
|
pub struct Block {
|
|
pub id: String,
|
|
pub content: String,
|
|
pub children: Vec<Block>,
|
|
pub properties: HashMap<String, String>,
|
|
pub task_status: Option<TaskStatus>,
|
|
pub tags: Vec<String>,
|
|
pub references: Vec<String>, // [[wikilinks]]
|
|
}
|
|
|
|
pub enum TaskStatus {
|
|
TODO,
|
|
DOING,
|
|
DONE,
|
|
LATER,
|
|
NOW,
|
|
WAITING,
|
|
CANCELLED,
|
|
}
|
|
```
|
|
|
|
### Storage Trait
|
|
|
|
```rust
|
|
// kogral-core/src/storage/mod.rs
|
|
|
|
#[async_trait]
|
|
pub trait Storage: Send + Sync {
|
|
// ─── Node Operations ──────────────────────────────────────
|
|
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>>;
|
|
|
|
// ─── Edge Operations ──────────────────────────────────────
|
|
async fn create_edge(&self, edge: &Edge) -> Result<()>;
|
|
async fn get_edges(&self, node_id: &str, direction: EdgeDirection) -> Result<Vec<Edge>>;
|
|
async fn delete_edge(&self, source: &str, target: &str) -> Result<()>;
|
|
|
|
// ─── Search ───────────────────────────────────────────────
|
|
async fn search_text(&self, query: &str, limit: usize) -> Result<Vec<Node>>;
|
|
async fn search_semantic(&self, embedding: &[f32], limit: usize) -> Result<Vec<Node>>;
|
|
|
|
// ─── Graph Operations ─────────────────────────────────────
|
|
async fn get_connected(&self, node_id: &str, depth: usize) -> Result<Graph>;
|
|
async fn get_path(&self, from: &str, to: &str) -> Result<Option<Vec<Edge>>>;
|
|
}
|
|
|
|
// Implementations
|
|
pub struct FilesystemStorage {
|
|
base_path: PathBuf, // .kogral/
|
|
}
|
|
|
|
pub struct SurrealDbStorage {
|
|
client: Surreal<Client>,
|
|
namespace: String,
|
|
database: String,
|
|
}
|
|
|
|
pub struct MemoryStorage {
|
|
nodes: DashMap<String, Node>,
|
|
edges: DashMap<String, Vec<Edge>>,
|
|
}
|
|
```
|
|
|
|
### Embeddings
|
|
|
|
```rust
|
|
// kogral-core/src/embeddings.rs
|
|
|
|
pub enum EmbeddingProvider {
|
|
FastEmbed {
|
|
model: String, // "BAAI/bge-small-en-v1.5"
|
|
cache_dir: PathBuf,
|
|
},
|
|
RigCore {
|
|
provider: RigProvider, // OpenAI, Anthropic, etc.
|
|
model: 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;
|
|
fn model_name(&self) -> &str;
|
|
}
|
|
|
|
// FastEmbed: 384 dimensions, local, offline
|
|
pub struct FastEmbedder {
|
|
model: fastembed::TextEmbedding,
|
|
}
|
|
|
|
// RigCore: Cloud providers
|
|
pub struct RigEmbedder {
|
|
client: Box<dyn rig_core::Embedder>,
|
|
}
|
|
```
|
|
|
|
### CLI Commands
|
|
|
|
```bash
|
|
# ─── Initialization ────────────────────────────────────────────
|
|
kogral init # Create .kogral/ directory
|
|
kogral init --with-surreal # Also setup SurrealDB connection
|
|
|
|
# ─── Adding Content ────────────────────────────────────────────
|
|
kogral add note "Title" # Interactive note creation
|
|
kogral add decision "Title" # Guided ADR creation
|
|
kogral add guideline "Title" # Add team guideline
|
|
kogral add pattern "Title" # Document pattern
|
|
kogral add journal # Today's journal entry
|
|
|
|
# ─── Querying ──────────────────────────────────────────────────
|
|
kogral search "query" # Text search
|
|
kogral search --semantic "query" # Semantic search
|
|
kogral search --type decision # Filter by type
|
|
kogral search --tag auth # Filter by tag
|
|
|
|
# ─── Relationships ─────────────────────────────────────────────
|
|
kogral link <src> <dst> relates_to # Create relationship
|
|
kogral link <src> <dst> implements # Implementation link
|
|
kogral unlink <src> <dst> # Remove relationship
|
|
|
|
# ─── Viewing ───────────────────────────────────────────────────
|
|
kogral list # List all nodes
|
|
kogral list --type pattern # Filter by type
|
|
kogral show <id> # Display node details
|
|
kogral graph # Output DOT format
|
|
kogral graph --connected <id> # Subgraph from node
|
|
|
|
# ─── Sync & Export ─────────────────────────────────────────────
|
|
kogral sync # Sync filesystem ↔ SurrealDB
|
|
kogral export markdown # Export to markdown
|
|
kogral export json # Export to JSON
|
|
kogral import <path> # Import from Logseq/markdown
|
|
|
|
# ─── MCP Server ────────────────────────────────────────────────
|
|
kogral serve # Start MCP server (stdio)
|
|
kogral serve --port 3000 # HTTP mode
|
|
|
|
# ─── Configuration ─────────────────────────────────────────────
|
|
kogral config # Show current config
|
|
kogral config set <key> <value> # Set config value
|
|
```
|
|
|
|
### MCP Protocol
|
|
|
|
```rust
|
|
// kogral-mcp/src/protocol.rs
|
|
|
|
// ─── Tools ────────────────────────────────────────────────────
|
|
pub const TOOLS: &[Tool] = &[
|
|
Tool {
|
|
name: "search",
|
|
description: "Search knowledge graph",
|
|
input_schema: json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"query": { "type": "string" },
|
|
"node_type": { "type": "string", "optional": true },
|
|
"semantic": { "type": "boolean", "default": false },
|
|
"limit": { "type": "integer", "default": 10 }
|
|
},
|
|
"required": ["query"]
|
|
}),
|
|
},
|
|
Tool {
|
|
name: "add_note",
|
|
description: "Add a note to the knowledge graph",
|
|
input_schema: json!({...}),
|
|
},
|
|
Tool {
|
|
name: "add_decision",
|
|
description: "Record an architectural decision",
|
|
input_schema: json!({...}),
|
|
},
|
|
Tool {
|
|
name: "link",
|
|
description: "Create relationship between nodes",
|
|
input_schema: json!({...}),
|
|
},
|
|
Tool {
|
|
name: "get_guidelines",
|
|
description: "Get applicable guidelines",
|
|
input_schema: json!({...}),
|
|
},
|
|
Tool {
|
|
name: "list_graphs",
|
|
description: "List available knowledge graphs",
|
|
input_schema: json!({}),
|
|
},
|
|
Tool {
|
|
name: "export",
|
|
description: "Export knowledge graph",
|
|
input_schema: json!({...}),
|
|
},
|
|
];
|
|
|
|
// ─── Resources ────────────────────────────────────────────────
|
|
pub const RESOURCES: &[Resource] = &[
|
|
Resource {
|
|
uri: "kogral://project/notes",
|
|
name: "Project Notes",
|
|
description: "All notes in current project",
|
|
},
|
|
Resource {
|
|
uri: "kogral://project/decisions",
|
|
name: "Project Decisions",
|
|
description: "All ADRs in current project",
|
|
},
|
|
Resource {
|
|
uri: "kogral://project/guidelines",
|
|
name: "Project Guidelines",
|
|
description: "Effective guidelines (with inheritance)",
|
|
},
|
|
Resource {
|
|
uri: "kogral://project/patterns",
|
|
name: "Project Patterns",
|
|
description: "All patterns in current project",
|
|
},
|
|
Resource {
|
|
uri: "kogral://shared/guidelines",
|
|
name: "Shared Guidelines",
|
|
description: "Organization-wide guidelines",
|
|
},
|
|
Resource {
|
|
uri: "kogral://shared/patterns",
|
|
name: "Shared Patterns",
|
|
description: "Organization-wide patterns",
|
|
},
|
|
];
|
|
|
|
// ─── Prompts ──────────────────────────────────────────────────
|
|
pub const PROMPTS: &[Prompt] = &[
|
|
Prompt {
|
|
name: "summarize_project",
|
|
description: "Summarize project knowledge",
|
|
arguments: json!([]),
|
|
},
|
|
Prompt {
|
|
name: "find_related",
|
|
description: "Find related knowledge for a topic",
|
|
arguments: json!([
|
|
{ "name": "topic", "required": true }
|
|
]),
|
|
},
|
|
];
|
|
```
|
|
|
|
---
|
|
|
|
## 3. TypeDialog: Especificaciones Completas
|
|
|
|
### Workspace (8 crates)
|
|
|
|
```text
|
|
crates/
|
|
├── typedialog-core/ # Core library
|
|
│ ├── form/ # Form models
|
|
│ ├── field/ # Field types (8)
|
|
│ ├── validation/ # Validators
|
|
│ ├── backend/ # Backend trait
|
|
│ ├── backends/ # 6 implementations
|
|
│ ├── output/ # 4 output formats
|
|
│ ├── i18n/ # Fluent integration
|
|
│ └── nickel/ # Contract validation
|
|
├── typedialog/ # CLI binary
|
|
├── typedialog-tui/ # TUI binary
|
|
├── typedialog-web/ # Web binary
|
|
├── typedialog-ai/ # AI backend
|
|
├── typedialog-agent/
|
|
│ ├── typedialog-ag-core/ # Agent runtime
|
|
│ └── typedialog-ag/ # Agent CLI
|
|
└── typedialog-prov-gen/ # IaC generation
|
|
```
|
|
|
|
### Form Schema
|
|
|
|
```toml
|
|
# Form definition (TOML)
|
|
|
|
[form]
|
|
id = "example_form"
|
|
version = "1.0.0"
|
|
title = "Example Form"
|
|
description = "Demonstrates all features"
|
|
|
|
# ─── Sections ──────────────────────────────────────────────────
|
|
[[sections]]
|
|
id = "basic"
|
|
title = "Basic Information"
|
|
description = "Required fields"
|
|
|
|
[[sections.fields]]
|
|
id = "name"
|
|
type = "text"
|
|
label = "Full Name"
|
|
required = true
|
|
validation.min_length = 2
|
|
validation.max_length = 100
|
|
validation.pattern = "^[a-zA-Z\\s]+$"
|
|
|
|
[[sections.fields]]
|
|
id = "email"
|
|
type = "text"
|
|
label = "Email Address"
|
|
required = true
|
|
validation.pattern = "^[^@]+@[^@]+\\.[^@]+$"
|
|
|
|
[[sections.fields]]
|
|
id = "department"
|
|
type = "select"
|
|
label = "Department"
|
|
required = true
|
|
options = [
|
|
{ value = "engineering", label = "Engineering" },
|
|
{ value = "product", label = "Product" },
|
|
{ value = "design", label = "Design" },
|
|
]
|
|
|
|
# ─── Conditional Fields ────────────────────────────────────────
|
|
[[sections.fields]]
|
|
id = "team_size"
|
|
type = "select"
|
|
label = "Team Size"
|
|
condition = { field = "department", equals = "engineering" }
|
|
options = [
|
|
{ value = "small", label = "1-5" },
|
|
{ value = "medium", label = "6-20" },
|
|
{ value = "large", label = "20+" },
|
|
]
|
|
|
|
# ─── Multi-select ──────────────────────────────────────────────
|
|
[[sections.fields]]
|
|
id = "skills"
|
|
type = "multi-select"
|
|
label = "Skills"
|
|
display_mode = "grid" # list, grid, dropdown
|
|
options = [
|
|
{ value = "rust", label = "Rust" },
|
|
{ value = "typescript", label = "TypeScript" },
|
|
{ value = "python", label = "Python" },
|
|
{ value = "go", label = "Go" },
|
|
]
|
|
|
|
# ─── Repeating Groups ──────────────────────────────────────────
|
|
[[sections.fields]]
|
|
id = "projects"
|
|
type = "group"
|
|
label = "Previous Projects"
|
|
repeatable = true
|
|
min_items = 1
|
|
max_items = 5
|
|
|
|
[[sections.fields.fields]]
|
|
id = "project_name"
|
|
type = "text"
|
|
label = "Project Name"
|
|
|
|
[[sections.fields.fields]]
|
|
id = "project_role"
|
|
type = "select"
|
|
label = "Role"
|
|
options = [...]
|
|
|
|
# ─── Output ────────────────────────────────────────────────────
|
|
[output]
|
|
format = "json" # json, yaml, toml, nickel
|
|
validation = "nickel://schemas/employee.ncl"
|
|
template = "templates/output.tera"
|
|
```
|
|
|
|
### Backend Trait
|
|
|
|
```rust
|
|
// typedialog-core/src/backend/mod.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
|
|
}
|
|
|
|
fn supports_validation(&self) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
// ─── Backend Factory ──────────────────────────────────────────
|
|
pub enum BackendType {
|
|
Cli,
|
|
Tui,
|
|
Web,
|
|
Ai,
|
|
Agent,
|
|
ProvGen,
|
|
}
|
|
|
|
pub struct BackendFactory;
|
|
|
|
impl BackendFactory {
|
|
pub fn create(backend_type: BackendType, config: &Config) -> Box<dyn Backend> {
|
|
match backend_type {
|
|
BackendType::Cli => Box::new(CliBackend::new(config)),
|
|
BackendType::Tui => Box::new(TuiBackend::new(config)),
|
|
BackendType::Web => Box::new(WebBackend::new(config)),
|
|
BackendType::Ai => Box::new(AiBackend::new(config)),
|
|
BackendType::Agent => Box::new(AgentBackend::new(config)),
|
|
BackendType::ProvGen => Box::new(ProvGenBackend::new(config)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─── CLI Backend ──────────────────────────────────────────────
|
|
pub struct CliBackend {
|
|
theme: inquire::ui::RenderConfig,
|
|
}
|
|
|
|
// ─── TUI Backend ──────────────────────────────────────────────
|
|
pub struct TuiBackend {
|
|
terminal: Terminal<CrosstermBackend<Stdout>>,
|
|
}
|
|
|
|
// ─── Web Backend ──────────────────────────────────────────────
|
|
pub struct WebBackend {
|
|
port: u16,
|
|
templates: tera::Tera,
|
|
}
|
|
|
|
// ─── AI Backend ───────────────────────────────────────────────
|
|
pub struct AiBackend {
|
|
index: tantivy::Index,
|
|
embedder: Box<dyn Embedder>,
|
|
graph: petgraph::Graph<String, String>,
|
|
}
|
|
|
|
// ─── Agent Backend ────────────────────────────────────────────
|
|
pub struct AgentBackend {
|
|
providers: HashMap<String, Box<dyn LLMProvider>>,
|
|
templates: tera::Tera,
|
|
}
|
|
|
|
// ─── ProvGen Backend ──────────────────────────────────────────
|
|
pub struct ProvGenBackend {
|
|
templates: HashMap<CloudProvider, tera::Tera>,
|
|
validators: Vec<Box<dyn Validator>>,
|
|
}
|
|
```
|
|
|
|
### Agent MDX Format
|
|
|
|
```markdown
|
|
---
|
|
name: code_reviewer
|
|
version: "1.0"
|
|
provider: claude
|
|
model: claude-sonnet-4-20250514
|
|
temperature: 0.3
|
|
max_tokens: 4096
|
|
output_format: json
|
|
output_schema: |
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"issues": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"severity": { "enum": ["critical", "warning", "info"] },
|
|
"line": { "type": "integer" },
|
|
"message": { "type": "string" },
|
|
"suggestion": { "type": "string" }
|
|
}
|
|
}
|
|
},
|
|
"summary": { "type": "string" }
|
|
}
|
|
}
|
|
---
|
|
|
|
# Code Review Agent
|
|
|
|
## System
|
|
|
|
You are an expert code reviewer...
|
|
|
|
## User
|
|
|
|
Review this {{language}} code:
|
|
|
|
```{{language}}
|
|
{{code}}
|
|
```
|
|
|
|
Guidelines:
|
|
{{guidelines}}
|
|
```
|
|
|
|
### IaC Generation
|
|
|
|
```rust
|
|
// typedialog-prov-gen/src/lib.rs
|
|
|
|
pub enum CloudProvider {
|
|
Aws,
|
|
Gcp,
|
|
Azure,
|
|
Hetzner,
|
|
UpCloud,
|
|
Lxd,
|
|
}
|
|
|
|
pub struct InfraConfig {
|
|
pub provider: CloudProvider,
|
|
pub region: String,
|
|
pub environment: Environment,
|
|
pub resources: Vec<Resource>,
|
|
pub networking: NetworkConfig,
|
|
pub security: SecurityConfig,
|
|
pub tags: HashMap<String, String>,
|
|
}
|
|
|
|
pub struct Generator {
|
|
templates: HashMap<CloudProvider, tera::Tera>,
|
|
validators: ValidationPipeline, // 7 layers
|
|
}
|
|
|
|
impl Generator {
|
|
pub async fn generate(&self, config: &InfraConfig) -> Result<GeneratedIaC> {
|
|
// 1. Input validation
|
|
self.validators.validate_input(config)?;
|
|
|
|
// 2. Load provider template
|
|
let template = self.templates
|
|
.get(&config.provider)
|
|
.ok_or(Error::UnsupportedProvider)?;
|
|
|
|
// 3. Render Nickel
|
|
let nickel = template.render("main.ncl.tera", &config)?;
|
|
|
|
// 4. Validate generated Nickel
|
|
self.validators.validate_nickel(&nickel)?;
|
|
|
|
// 5. Split into files
|
|
let files = self.split_output(&nickel, config)?;
|
|
|
|
Ok(GeneratedIaC { provider: config.provider, files })
|
|
}
|
|
}
|
|
|
|
// 7-Layer Validation Pipeline
|
|
pub struct ValidationPipeline {
|
|
layers: Vec<Box<dyn Validator>>,
|
|
}
|
|
|
|
// Layers:
|
|
// 1. Schema validation (structure)
|
|
// 2. Type validation (Nickel contracts)
|
|
// 3. Provider validation (provider-specific rules)
|
|
// 4. Security validation (no exposed secrets)
|
|
// 5. Cost validation (budget limits)
|
|
// 6. Compliance validation (policy rules)
|
|
// 7. Integration validation (cross-resource refs)
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Provisioning: Especificaciones Completas
|
|
|
|
### Directory Structure
|
|
|
|
```text
|
|
provisioning/
|
|
├── core/
|
|
│ ├── cli/ # Main CLI (211 lines)
|
|
│ ├── nulib/ # Nushell libraries
|
|
│ │ ├── config.nu # 476+ accessors
|
|
│ │ ├── provider.nu # Provider abstraction
|
|
│ │ ├── workflow.nu # Workflow execution
|
|
│ │ └── utils.nu # Utilities
|
|
│ └── scripts/ # Automation scripts
|
|
├── extensions/
|
|
│ ├── providers/
|
|
│ │ ├── aws/ # AWS provider
|
|
│ │ ├── upcloud/ # UpCloud provider
|
|
│ │ └── local/ # Local (LXD) provider
|
|
│ ├── taskservs/ # 50+ services
|
|
│ ├── clusters/ # Deployment templates
|
|
│ └── workflows/ # Workflow definitions
|
|
├── platform/
|
|
│ ├── orchestrator/ # Rust workflow engine
|
|
│ ├── control-center/ # Axum backend
|
|
│ ├── control-center-ui/ # Leptos frontend
|
|
│ ├── installer/ # Multi-mode installer
|
|
│ ├── mcp-server/ # MCP server
|
|
│ ├── ai-service/ # AI operations
|
|
│ ├── rag/ # RAG system
|
|
│ ├── vault-service/ # Secrets management
|
|
│ ├── detector/ # Anomaly detection
|
|
│ ├── extension-registry/ # Extension catalog
|
|
│ └── provisioning-daemon/ # Service daemon
|
|
├── schemas/ # Nickel schemas
|
|
│ ├── server.ncl
|
|
│ ├── network.ncl
|
|
│ ├── storage.ncl
|
|
│ ├── kubernetes.ncl
|
|
│ └── security.ncl
|
|
└── docs/ # Documentation
|
|
```
|
|
|
|
### Nickel Schemas
|
|
|
|
```nickel
|
|
# schemas/server.ncl
|
|
|
|
let Server = {
|
|
name
|
|
| String
|
|
| doc "Server hostname",
|
|
|
|
provider
|
|
| [ | 'aws, 'upcloud, 'local |]
|
|
| doc "Cloud provider",
|
|
|
|
spec
|
|
| {
|
|
cpu
|
|
| Number
|
|
| default = 2
|
|
| doc "CPU cores",
|
|
memory_gb
|
|
| Number
|
|
| default = 4
|
|
| doc "Memory in GB",
|
|
disk_gb
|
|
| Number
|
|
| default = 50
|
|
| doc "Root disk in GB",
|
|
os
|
|
| {
|
|
family | [ | 'ubuntu, 'debian, 'rocky |],
|
|
version | String,
|
|
},
|
|
},
|
|
|
|
networking
|
|
| {
|
|
vpc | String | optional,
|
|
subnet | String | optional,
|
|
public_ip | Bool | default = false,
|
|
security_groups | Array String | default = [],
|
|
private_ip | String | optional,
|
|
},
|
|
|
|
storage
|
|
| Array {
|
|
name | String,
|
|
size_gb | Number,
|
|
type | [ | 'ssd, 'hdd, 'nvme |] | default = 'ssd,
|
|
mount_point | String,
|
|
}
|
|
| default = [],
|
|
|
|
tags
|
|
| { _ : String }
|
|
| default = {},
|
|
|
|
metadata
|
|
| { _ : Dyn }
|
|
| default = {},
|
|
}
|
|
in Server
|
|
```
|
|
|
|
### Orchestrator
|
|
|
|
```rust
|
|
// platform/orchestrator/src/lib.rs
|
|
|
|
pub struct Orchestrator {
|
|
state: StateManager,
|
|
executor: WorkflowExecutor,
|
|
scheduler: Scheduler,
|
|
providers: HashMap<String, Box<dyn Provider>>,
|
|
}
|
|
|
|
impl Orchestrator {
|
|
pub async fn execute(&self, workflow: Workflow) -> Result<ExecutionResult> {
|
|
// 1. Create checkpoint
|
|
let checkpoint = self.state.checkpoint(&workflow)?;
|
|
|
|
// 2. Resolve dependencies (topological sort)
|
|
let tasks = self.resolve_dependencies(&workflow)?;
|
|
|
|
// 3. Execute with retry
|
|
for task in tasks {
|
|
let result = self.execute_with_retry(&task).await;
|
|
|
|
match result {
|
|
Ok(output) => {
|
|
self.state.record_success(&task, &output)?;
|
|
}
|
|
Err(e) => {
|
|
// Rollback to checkpoint
|
|
self.state.rollback(&checkpoint)?;
|
|
return Err(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(ExecutionResult::success())
|
|
}
|
|
|
|
async fn execute_with_retry(&self, task: &Task) -> Result<Output> {
|
|
let mut attempts = 0;
|
|
let max_attempts = task.retry_config.max_attempts;
|
|
|
|
loop {
|
|
attempts += 1;
|
|
match self.executor.run(task).await {
|
|
Ok(output) => return Ok(output),
|
|
Err(e) if attempts < max_attempts => {
|
|
let delay = self.calculate_backoff(attempts);
|
|
tokio::time::sleep(delay).await;
|
|
}
|
|
Err(e) => return Err(e),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn calculate_backoff(&self, attempt: u32) -> Duration {
|
|
// Exponential backoff: 2^attempt * base_delay
|
|
Duration::from_secs(2u64.pow(attempt) * self.config.base_delay_secs)
|
|
}
|
|
}
|
|
|
|
// ─── State Management ─────────────────────────────────────────
|
|
pub struct StateManager {
|
|
store: Box<dyn StateStore>,
|
|
}
|
|
|
|
impl StateManager {
|
|
pub fn checkpoint(&self, workflow: &Workflow) -> Result<Checkpoint> {
|
|
let state = self.capture_current_state(workflow)?;
|
|
let id = self.store.save_checkpoint(&state)?;
|
|
Ok(Checkpoint { id, state })
|
|
}
|
|
|
|
pub fn rollback(&self, checkpoint: &Checkpoint) -> Result<()> {
|
|
self.restore_state(&checkpoint.state)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Security Layer
|
|
|
|
```rust
|
|
// platform/control-center/src/security/
|
|
|
|
// ─── Authentication ───────────────────────────────────────────
|
|
pub struct AuthService {
|
|
jwt_secret: Secret<String>,
|
|
hasher: Argon2Config,
|
|
mfa: MfaService,
|
|
}
|
|
|
|
impl AuthService {
|
|
pub async fn authenticate(&self, credentials: Credentials) -> Result<Token> {
|
|
// 1. Verify password
|
|
let user = self.verify_password(&credentials)?;
|
|
|
|
// 2. Check MFA if enabled
|
|
if user.mfa_enabled {
|
|
self.mfa.verify(&user, &credentials.mfa_code)?;
|
|
}
|
|
|
|
// 3. Generate JWT
|
|
let token = self.generate_jwt(&user)?;
|
|
|
|
// 4. Audit log
|
|
self.audit.log_authentication(&user, AuthResult::Success)?;
|
|
|
|
Ok(token)
|
|
}
|
|
}
|
|
|
|
// ─── MFA Service ──────────────────────────────────────────────
|
|
pub struct MfaService {
|
|
totp: TotpProvider,
|
|
webauthn: WebAuthnProvider,
|
|
}
|
|
|
|
impl MfaService {
|
|
pub fn verify(&self, user: &User, code: &MfaCode) -> Result<()> {
|
|
match &user.mfa_method {
|
|
MfaMethod::Totp => self.totp.verify(&user.totp_secret, code),
|
|
MfaMethod::WebAuthn => self.webauthn.verify(&user.credentials, code),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ─── Authorization (Cedar) ────────────────────────────────────
|
|
pub struct AuthzService {
|
|
engine: cedar_policy::Authorizer,
|
|
policies: cedar_policy::PolicySet,
|
|
}
|
|
|
|
impl AuthzService {
|
|
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)
|
|
}
|
|
}
|
|
|
|
// ─── KMS ──────────────────────────────────────────────────────
|
|
pub enum KmsBackend {
|
|
RustyVault(RustyVaultClient),
|
|
Age(AgeClient),
|
|
AwsKms(AwsKmsClient),
|
|
HashiVault(VaultClient),
|
|
Cosmian(CosmianClient),
|
|
}
|
|
|
|
pub struct KmsService {
|
|
backend: KmsBackend,
|
|
}
|
|
|
|
impl KmsService {
|
|
pub async fn encrypt(&self, plaintext: &[u8], key_id: &str) -> Result<Vec<u8>> {
|
|
// Envelope encryption
|
|
let dek = self.generate_dek()?;
|
|
let ciphertext = self.encrypt_with_dek(plaintext, &dek)?;
|
|
let encrypted_dek = self.wrap_key(&dek, key_id).await?;
|
|
|
|
Ok(self.package(ciphertext, encrypted_dek))
|
|
}
|
|
|
|
pub async fn decrypt(&self, blob: &[u8], key_id: &str) -> Result<Vec<u8>> {
|
|
let (ciphertext, encrypted_dek) = self.unpackage(blob)?;
|
|
let dek = self.unwrap_key(&encrypted_dek, key_id).await?;
|
|
self.decrypt_with_dek(&ciphertext, &dek)
|
|
}
|
|
}
|
|
|
|
// ─── Audit ────────────────────────────────────────────────────
|
|
pub struct AuditService {
|
|
store: Box<dyn AuditStore>,
|
|
retention_years: u32, // 7 years
|
|
}
|
|
|
|
impl AuditService {
|
|
pub fn log(&self, event: AuditEvent) -> Result<()> {
|
|
let record = AuditRecord {
|
|
id: Uuid::new_v4(),
|
|
timestamp: Utc::now(),
|
|
event,
|
|
user_id: current_user_id()?,
|
|
ip_address: current_ip()?,
|
|
user_agent: current_user_agent()?,
|
|
};
|
|
|
|
self.store.save(&record)
|
|
}
|
|
|
|
pub fn export(&self, format: ExportFormat, range: DateRange) -> Result<Vec<u8>> {
|
|
let records = self.store.query(range)?;
|
|
|
|
match format {
|
|
ExportFormat::Json => serde_json::to_vec(&records),
|
|
ExportFormat::Csv => self.to_csv(&records),
|
|
ExportFormat::Parquet => self.to_parquet(&records),
|
|
ExportFormat::Avro => self.to_avro(&records),
|
|
ExportFormat::Pdf => self.to_pdf(&records),
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### MCP Server
|
|
|
|
```rust
|
|
// platform/mcp-server/src/tools.rs
|
|
|
|
pub const TOOLS: &[Tool] = &[
|
|
// ─── Query Tools ──────────────────────────────────────────
|
|
Tool {
|
|
name: "query_infrastructure",
|
|
description: "Query infrastructure state using natural language",
|
|
input_schema: json!({
|
|
"query": { "type": "string" },
|
|
"provider": { "type": "string", "optional": true }
|
|
}),
|
|
},
|
|
|
|
// ─── Generation Tools ─────────────────────────────────────
|
|
Tool {
|
|
name: "generate_config",
|
|
description: "Generate Nickel configuration from description",
|
|
input_schema: json!({
|
|
"description": { "type": "string" },
|
|
"provider": { "type": "string" },
|
|
"resource_type": { "type": "string" }
|
|
}),
|
|
},
|
|
|
|
// ─── Validation Tools ─────────────────────────────────────
|
|
Tool {
|
|
name: "validate_config",
|
|
description: "Validate Nickel configuration",
|
|
input_schema: json!({
|
|
"config": { "type": "string" },
|
|
"strict": { "type": "boolean", "default": true }
|
|
}),
|
|
},
|
|
|
|
// ─── Cost Tools ───────────────────────────────────────────
|
|
Tool {
|
|
name: "estimate_cost",
|
|
description: "Estimate monthly cost for configuration",
|
|
input_schema: json!({
|
|
"config": { "type": "string" },
|
|
"region": { "type": "string", "optional": true }
|
|
}),
|
|
},
|
|
|
|
// ─── Compliance Tools ─────────────────────────────────────
|
|
Tool {
|
|
name: "check_compliance",
|
|
description: "Check configuration against compliance rules",
|
|
input_schema: json!({
|
|
"config": { "type": "string" },
|
|
"framework": { "enum": ["soc2", "hipaa", "gdpr", "pci"] }
|
|
}),
|
|
},
|
|
|
|
// ─── Migration Tools ──────────────────────────────────────
|
|
Tool {
|
|
name: "plan_migration",
|
|
description: "Generate migration plan between configurations",
|
|
input_schema: json!({
|
|
"current": { "type": "string" },
|
|
"target": { "type": "string" }
|
|
}),
|
|
},
|
|
|
|
// ─── Execution Tools ──────────────────────────────────────
|
|
Tool {
|
|
name: "execute_workflow",
|
|
description: "Execute provisioning workflow",
|
|
input_schema: json!({
|
|
"workflow_id": { "type": "string" },
|
|
"dry_run": { "type": "boolean", "default": true }
|
|
}),
|
|
},
|
|
];
|
|
```
|
|
|
|
---
|
|
|
|
## 5. SecretumVault: Especificaciones Completas
|
|
|
|
### Arquitectura (~11K LOC, 50+ tests)
|
|
|
|
```text
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ SecretumVault │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
|
│ │ 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
|
|
|
|
```rust
|
|
// 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
|
|
|
|
| Backend | Algoritmos | Estado |
|
|
| --------- | ------------ | -------- |
|
|
| **OpenSSL** | RSA-2048/4096, ECDSA (P-256/384/521), AES-256-GCM | ✅ Producción |
|
|
| **OQS** | ML-KEM-768, ML-DSA-65 (NIST FIPS 203/204) | ✅ **Producción (PQC)** |
|
|
| **AWS-LC** | RSA, ECDSA (PQC experimental) | ⚠️ Experimental |
|
|
| **RustCrypto** | AES-256-GCM, ChaCha20-Poly1305 | ⚠️ Testing |
|
|
|
|
### Secrets Engines
|
|
|
|
```rust
|
|
// 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 Secret Sharing)
|
|
|
|
```rust
|
|
// 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> },
|
|
}
|
|
```
|
|
|
|
### API Endpoints
|
|
|
|
```rust
|
|
// 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))
|
|
```
|
|
|
|
### CLI Commands
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```toml
|
|
# Cargo.toml features
|
|
[features]
|
|
default = ["openssl", "filesystem", "server", "pqc"]
|
|
|
|
# Crypto backends
|
|
openssl = ["dep:openssl"]
|
|
aws-lc = ["dep:aws-lc-rs"]
|
|
pqc = ["dep:oqs"]
|
|
|
|
# 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 Cross-Project
|
|
|
|
### SurrealDB Schema Compartido
|
|
|
|
```sql
|
|
-- ─── Namespace ────────────────────────────────────────────────
|
|
DEFINE NAMESPACE portfolio;
|
|
|
|
-- ─── Databases ────────────────────────────────────────────────
|
|
DEFINE DATABASE vapora;
|
|
DEFINE DATABASE kogral;
|
|
DEFINE DATABASE typedialog;
|
|
DEFINE DATABASE provisioning;
|
|
DEFINE DATABASE secretumvault;
|
|
|
|
-- ─── Shared Tables ────────────────────────────────────────────
|
|
|
|
-- Execution records (cross-project)
|
|
DEFINE TABLE executions SCHEMAFULL;
|
|
DEFINE FIELD project ON executions TYPE string;
|
|
DEFINE FIELD source ON executions TYPE string; -- vapora, kogral, etc.
|
|
DEFINE FIELD task_type ON executions TYPE string;
|
|
DEFINE FIELD agent_id ON executions TYPE option<string>;
|
|
DEFINE FIELD status ON executions TYPE string;
|
|
DEFINE FIELD duration_ms ON executions TYPE int;
|
|
DEFINE FIELD metadata ON executions FLEXIBLE TYPE object;
|
|
DEFINE FIELD created_at ON executions TYPE datetime DEFAULT time::now();
|
|
|
|
DEFINE INDEX idx_executions_project ON executions FIELDS project;
|
|
DEFINE INDEX idx_executions_source ON executions FIELDS source;
|
|
DEFINE INDEX idx_executions_created ON executions FIELDS created_at;
|
|
|
|
-- Knowledge references (Kogral → others)
|
|
DEFINE TABLE knowledge_refs SCHEMAFULL;
|
|
DEFINE FIELD source_project ON knowledge_refs TYPE string;
|
|
DEFINE FIELD node_id ON knowledge_refs TYPE string;
|
|
DEFINE FIELD target_project ON knowledge_refs TYPE string;
|
|
DEFINE FIELD target_id ON knowledge_refs TYPE string;
|
|
DEFINE FIELD ref_type ON knowledge_refs TYPE string; -- guideline, pattern, decision
|
|
DEFINE FIELD created_at ON knowledge_refs TYPE datetime DEFAULT time::now();
|
|
|
|
-- Configuration snapshots (TypeDialog → Provisioning)
|
|
DEFINE TABLE config_snapshots SCHEMAFULL;
|
|
DEFINE FIELD form_id ON config_snapshots TYPE string;
|
|
DEFINE FIELD config_hash ON config_snapshots TYPE string;
|
|
DEFINE FIELD output ON config_snapshots FLEXIBLE TYPE object;
|
|
DEFINE FIELD target ON config_snapshots TYPE string; -- provisioning workflow
|
|
DEFINE FIELD created_at ON config_snapshots TYPE datetime DEFAULT time::now();
|
|
```
|
|
|
|
### Integration Patterns
|
|
|
|
```rust
|
|
// Example: Kogral → Vapora integration
|
|
|
|
// Vapora agent queries Kogral for guidelines before generating code
|
|
async fn get_project_context(task: &Task) -> Result<ProjectContext> {
|
|
let kogral = KogralMcpClient::connect().await?;
|
|
|
|
// Get applicable guidelines
|
|
let guidelines = kogral.call("get_guidelines", json!({
|
|
"topic": &task.task_type,
|
|
"include_shared": true,
|
|
})).await?;
|
|
|
|
// Get relevant patterns
|
|
let patterns = kogral.call("search", json!({
|
|
"query": &task.description,
|
|
"node_type": "pattern",
|
|
"semantic": true,
|
|
"limit": 5,
|
|
})).await?;
|
|
|
|
// Get related decisions
|
|
let decisions = kogral.call("search", json!({
|
|
"query": &task.description,
|
|
"node_type": "decision",
|
|
"limit": 3,
|
|
})).await?;
|
|
|
|
Ok(ProjectContext { guidelines, patterns, decisions })
|
|
}
|
|
|
|
// Example: TypeDialog → Provisioning integration
|
|
|
|
// TypeDialog prov-gen backend generates Nickel for Provisioning
|
|
async fn generate_infrastructure(form_response: &FormResponse) -> Result<WorkflowId> {
|
|
// Generate Nickel config from form
|
|
let generator = ProvGenBackend::new();
|
|
let iac = generator.generate(&form_response.into()).await?;
|
|
|
|
// Submit to Provisioning
|
|
let provisioning = ProvisioningClient::connect().await?;
|
|
let workflow_id = provisioning.submit_workflow(iac).await?;
|
|
|
|
// Record in shared DB
|
|
let db = SurrealClient::connect().await?;
|
|
db.create("config_snapshots", ConfigSnapshot {
|
|
form_id: form_response.form_id.clone(),
|
|
config_hash: hash(&iac),
|
|
output: form_response.values.clone(),
|
|
target: workflow_id.clone(),
|
|
}).await?;
|
|
|
|
Ok(workflow_id)
|
|
}
|
|
|
|
// Example: Vapora → Kogral integration
|
|
|
|
// Record agent execution as Kogral Execution node
|
|
async fn record_execution(result: &TaskResult) -> Result<()> {
|
|
let kogral = KogralMcpClient::connect().await?;
|
|
|
|
kogral.call("add_execution", json!({
|
|
"task_id": &result.task_id,
|
|
"agent_role": &result.agent_role,
|
|
"status": &result.status,
|
|
"duration_ms": result.duration_ms,
|
|
"tokens_used": result.tokens_used,
|
|
"output_summary": &result.summary,
|
|
})).await?;
|
|
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Métricas y Calidad
|
|
|
|
| Proyecto | Crates | Tests | LOC | Clippy | Unsafe | Doc |
|
|
| ---------- | -------- | ------- | ----- | -------- | -------- | ----- |
|
|
| Vapora | 13 | 218 | ~50K | 0 warn | 0 | 100% pub |
|
|
| Kogral | 3 | 56 | ~15K | 0 warn | 0 | 100% pub |
|
|
| TypeDialog | 8 | 3,818 | ~90K | 0 warn | 0 | 100% pub |
|
|
| Provisioning | 15+ | 218 | ~40K | 0 warn | 0 | 100% pub |
|
|
| SecretumVault | 1 | 50+ | ~11K | 0 warn | 0 | 100% pub |
|
|
| **Total** | **40+** | **4,360+** | **~206K** | **0** | **0** | **100%** |
|
|
|
|
### Verification Commands
|
|
|
|
```bash
|
|
# All projects
|
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
|
cargo test --workspace
|
|
cargo doc --workspace --no-deps
|
|
|
|
# Coverage
|
|
cargo tarpaulin --workspace --out Html
|
|
|
|
# Security audit
|
|
cargo audit
|
|
|
|
# Benchmarks
|
|
cargo bench --workspace
|
|
```
|
|
|
|
---
|
|
|
|
*Documento generado: 2026-01-22*
|
|
*Tipo: info (especificaciones técnicas completas)*
|