tawasuyu

tawasuyu/brahman

Rust 463TOML 180Markdown 49JSON 176353 Definiciones

feat(agorapura): app demo — escenario narrado del ágora

CLI que recorre el caso canónico de extremo a extremo: Venezuela
atestigua la nacionalidad de Yumaira, otras identidades corroboran,
una firma manipulada se rechaza, y tres políticas negociadas dan
veredictos distintos sobre la misma evidencia. cargo run -p agorapura.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

4e27065a153c988ebbd435dc3cd8ffd1c0e38c4f · por sergio · (hace 5 meses) · padre c1c136954 · ver el árbol en este commit

Delta semántico · 2

crates/apps/agorapura/src/main.rs

4 archivos · +117 −0

diff --git a/Cargo.lock b/Cargo.lock
index cb340e1..69a8e35 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -80,6 +80,14 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "agorapura"
+version = "0.1.0"
+dependencies = [
+ "agorapura-core",
+ "agorapura-graph",
+]
+
 [[package]]
 name = "agorapura-core"
 version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index 95bf776..f815254 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -235,6 +235,7 @@ members = [
     "crates/apps/cosmobiologia-server",
     "crates/apps/dominium",
     "crates/apps/fana",
+    "crates/apps/agorapura",
 ]
 
 [workspace.package]
diff --git a/crates/apps/agorapura/Cargo.toml b/crates/apps/agorapura/Cargo.toml
new file mode 100644
index 0000000..59436a9
--- /dev/null
+++ b/crates/apps/agorapura/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "agorapura"
+version.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+license.workspace = true
+authors.workspace = true
+publish.workspace = true
+description = "agorapura — demostración narrada del ágora de identidad: identidades, claims, atestaciones firmadas y evaluación de confianza bajo políticas negociadas."
+
+[[bin]]
+name = "agorapura"
+path = "src/main.rs"
+
+[dependencies]
+agorapura-core = { path = "../../modules/agorapura/agorapura-core" }
+agorapura-graph = { path = "../../modules/agorapura/agorapura-graph" }
diff --git a/crates/apps/agorapura/src/main.rs b/crates/apps/agorapura/src/main.rs
new file mode 100644
index 0000000..b082c35
--- /dev/null
+++ b/crates/apps/agorapura/src/main.rs
@@ -0,0 +1,91 @@
+//! `agorapura` — demostración narrada del ágora de identidad.
+//!
+//! Recorre el escenario canónico de extremo a extremo: la institución
+//! *Venezuela* atestigua la nacionalidad de la persona *Yumaira*, y
+//! otras identidades la corroboran. Imprime la evidencia acumulada y
+//! cómo distintas políticas *negociadas* la aceptan o no.
+//!
+//! No es la app definitiva — es un smoke test legible y la mejor forma
+//! de ver el módulo funcionando: `cargo run -p agorapura`.
+
+use agorapura_core::{Attestation, Claim, IdentityKind, Keypair};
+use agorapura_graph::{TrustGraph, TrustPolicy};
+
+/// Segundo Unix fijo para que la demo sea reproducible.
+const T0: u64 = 1_700_000_000;
+
+fn main() {
+    println!("\n  ágora · demostración de identidad federada\n");
+
+    // --- Identidades. Semillas fijas → demo reproducible. ---
+    let yumaira = Keypair::from_seed([20; 32]);
+    let venezuela = Keypair::from_seed([10; 32]);
+    let comunidad = Keypair::from_seed([30; 32]);
+    let vecina = Keypair::from_seed([40; 32]);
+
+    let mut agora = TrustGraph::new();
+    agora.register(yumaira.identity(IdentityKind::Person, "Yumaira"));
+    agora.register(venezuela.identity(IdentityKind::Institution, "Venezuela"));
+    agora.register(comunidad.identity(IdentityKind::Community, "Vecinos del Valle"));
+    agora.register(vecina.identity(IdentityKind::Person, "Carmen"));
+
+    println!("  identidades registradas:");
+    for kp in [&yumaira, &venezuela, &comunidad, &vecina] {
+        let id = kp.identity_id();
+        let name = agora.identity(id).map(|i| i.display_name.as_str()).unwrap_or("?");
+        println!("    {id}  {name}");
+    }
+
+    // --- Atestaciones sobre la nacionalidad de Yumaira. ---
+    let nacionalidad = |by: &Keypair| {
+        Attestation::create(
+            by,
+            Claim::new(yumaira.identity_id(), "nacionalidad", "venezolana", T0),
+        )
+    };
+    println!("\n  atestaciones de «nacionalidad = venezolana» sobre Yumaira:");
+    for (by, label) in [
+        (&venezuela, "Venezuela (institución)"),
+        (&comunidad, "Vecinos del Valle (comunidad)"),
+        (&yumaira, "Yumaira (ella misma)"),
+    ] {
+        let att = nacionalidad(by);
+        match agora.add_attestation(att) {
+            Ok(()) => println!("    ✔ firma verificada — {label}"),
+            Err(e) => println!("    ✘ rechazada — {label}: {e}"),
+        }
+    }
+
+    // --- Intento de fraude: una firma manipulada. ---
+    let mut falsa = nacionalidad(&vecina);
+    falsa.claim.value = "marciana".into(); // rompe la firma
+    print!("\n  intento de atestación con firma manipulada: ");
+    match agora.add_attestation(falsa) {
+        Ok(()) => println!("ACEPTADA (esto sería un bug)"),
+        Err(e) => println!("rechazada — {e}"),
+    }
+
+    // --- Corroboración. ---
+    let c = agora.corroboration(yumaira.identity_id(), "nacionalidad", "venezolana");
+    println!("\n  corroboración del claim:");
+    println!("    atestadores totales : {}", c.total());
+    println!("    terceros (no ella)  : {}", c.third_party());
+    println!("    auto-atestado       : {}", c.self_attested);
+
+    // --- Veredicto según la política negociada. ---
+    println!("\n  veredicto según la política (la verdad depende de lo pactado):");
+    for (policy, label) in [
+        (TrustPolicy::strict(1), "laxa  · 1 tercero basta"),
+        (TrustPolicy::strict(2), "media · 2 terceros"),
+        (TrustPolicy::strict(3), "estricta · 3 terceros"),
+    ] {
+        let ok = policy.accepts(&c);
+        let mark = if ok { "ACEPTA" } else { "rechaza" };
+        println!("    [{mark}]  {label}");
+    }
+
+    println!(
+        "\n  el ágora no dicta la verdad: acumula evidencia firmada y\n  \
+         cada quien la pesa con la política que negocie.\n"
+    );
+}