import spaces # must be imported before anything that touches CUDA, even though this app is CPU-only import subprocess from pathlib import Path import gradio as gr ROOT = Path(__file__).parent.resolve() BINARY_PATH = ROOT / "target" / "release" / "ubda_engine" TRUST_MATRIX = [ ["T-1", "Compromised", "Hard anomaly / intrusion interrupt", "None — active keys revoked, state frozen"], ["T0", "Unauthenticated", "Cold boot / sealed state", "None — payload & metadata encrypted"], ["T1", "Device Authenticated", "Hardware-backed passkey / attestation", "D0 — OS shell, public binaries, non-sensitive configs"], ["T2", "Behavioral Continuity", "Validated telemetry (T1 + BTE assertion)", "D1 — standard personal files, documents"], ["T3", "High Assurance", "Hardware biometric / local PIN (T2 + step-up)", "D2 — financial, medical, private records"], ["T4", "Critical Elevation", "Hardware HSM / out-of-band token (T3 + elevation)", "D3 — root signing keys, master vault seeds"], ] ARCHITECTURE_NOTE = """ **UBDA (Unified Behavioral Data Access) — V1.2-alpha** This is a prototype capability-based access-control engine written in Rust. A software *Behavioral Trust Engine* can only ever propose a trust level; a separate, hardware-style *Key Authority* independently validates that trust level against a resource's data classification before it signs a short-lived, single-use Data Access Capability (DAC). A *Key Broker* then re-verifies the DAC's signature, expiry, trust requirement, operation, and session binding — and rejects replay — before deriving an ephemeral session key. Click **Run protocol walkthrough** below to execute the actual compiled Rust binary and watch it move through all six stages of the protocol: reaching T2 via behavioral continuity, a rejected over-privileged request, a full issue → verify → derive-key cycle, a blocked replay attempt, a blocked signature-tampering attempt, and a compromise lockout + recovery reset. *(First click may take a little longer — the engine compiles the Rust source the first time it's needed, then reuses the built binary after that.)* ⚠️ Prototype / educational project — not a production security product. Source: see the linked GitHub repository. """ @spaces.GPU def _zerogpu_keepalive(): """No-op. This Space is CPU-only (compiling/running a Rust binary), but ZeroGPU hardware requires at least one @spaces.GPU-decorated function to exist or the Space fails to initialize. This satisfies that requirement without ever actually requesting GPU time for real work.""" return None def ensure_built() -> str | None: """Compile the Rust engine if it hasn't been built yet. Returns an error string, or None on success.""" if BINARY_PATH.exists(): return None try: result = subprocess.run( ["cargo", "build", "--release", "--locked"], cwd=str(ROOT), capture_output=True, text=True, timeout=300, ) if result.returncode != 0 or not BINARY_PATH.exists(): return f"Build failed:\n{result.stdout}\n{result.stderr}" return None except Exception as exc: # noqa: BLE001 return f"Build failed: {exc}" def run_walkthrough(): build_error = ensure_built() if build_error: return build_error try: result = subprocess.run( [str(BINARY_PATH)], capture_output=True, text=True, timeout=15, ) output = result.stdout if result.returncode != 0: output += f"\n\n[process exited with code {result.returncode}]\n{result.stderr}" return output except Exception as exc: # noqa: BLE001 return f"Failed to run the engine: {exc}" with gr.Blocks(title="UBDA Engine Demo") as demo: gr.Markdown(ARCHITECTURE_NOTE) run_btn = gr.Button("▶ Run protocol walkthrough", variant="primary") output_box = gr.Textbox(label="Engine output", lines=24, show_copy_button=True) run_btn.click(fn=run_walkthrough, outputs=output_box) gr.Markdown("### Trust-state matrix") gr.Dataframe( headers=["State", "Name", "Minimum gatekeeper requirement", "Accessible data classification"], value=TRUST_MATRIX, interactive=False, wrap=True, ) if __name__ == "__main__": demo.launch()